Loading packages/SystemUI/res/layout/clipboard_overlay.xml +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ <com.android.systemui.clipboardoverlay.DraggableConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:alpha="0" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +2 −2 Original line number Diff line number Diff line Loading @@ -60,8 +60,8 @@ public class ClipboardListener extends CoreStartable return; } if (mClipboardOverlayController == null) { mClipboardOverlayController = new ClipboardOverlayController(mContext, new TimeoutHandler(mContext)); mClipboardOverlayController = new ClipboardOverlayController(mContext, new TimeoutHandler(mContext)); } mClipboardOverlayController.setClipData(mClipboardManager.getPrimaryClip()); mClipboardOverlayController.setOnSessionCompleteListener(() -> { Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java +71 −11 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.MainThread; import android.app.RemoteAction; import android.content.BroadcastReceiver; import android.content.ClipData; import android.content.ComponentName; Loading @@ -43,6 +44,7 @@ import android.graphics.drawable.Icon; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Looper; import android.text.TextUtils; import android.util.Log; Loading @@ -60,8 +62,13 @@ import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.policy.PhoneWindow; Loading @@ -71,6 +78,7 @@ import com.android.systemui.screenshot.ScreenshotActionChip; import com.android.systemui.screenshot.TimeoutHandler; import java.io.IOException; import java.util.ArrayList; /** * Controls state and UI for the overlay that appears when something is added to the clipboard Loading @@ -93,6 +101,7 @@ public class ClipboardOverlayController { private final PhoneWindow mWindow; private final TimeoutHandler mTimeoutHandler; private final AccessibilityManager mAccessibilityManager; private final TextClassifier mTextClassifier; private final DraggableConstraintLayout mView; private final ImageView mImagePreview; Loading @@ -101,9 +110,13 @@ public class ClipboardOverlayController { private final ScreenshotActionChip mRemoteCopyChip; private final View mActionContainerBackground; private final View mDismissButton; private final LinearLayout mActionContainer; private final ArrayList<ScreenshotActionChip> mActionChips = new ArrayList<>(); private Runnable mOnSessionCompleteListener; private InputMonitor mInputMonitor; private InputEventReceiver mInputEventReceiver; private BroadcastReceiver mCloseDialogsReceiver; Loading @@ -117,6 +130,8 @@ public class ClipboardOverlayController { mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null); mAccessibilityManager = AccessibilityManager.getInstance(mContext); mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class)) .getTextClassifier(); mWindowManager = mContext.getSystemService(WindowManager.class); Loading @@ -134,8 +149,9 @@ public class ClipboardOverlayController { mView = (DraggableConstraintLayout) LayoutInflater.from(mContext).inflate(R.layout.clipboard_overlay, null); mActionContainerBackground = requireNonNull( mView.findViewById(R.id.actions_container_background)); mActionContainerBackground = requireNonNull(mView.findViewById(R.id.actions_container_background)); mActionContainer = requireNonNull(mView.findViewById(R.id.actions)); mImagePreview = requireNonNull(mView.findViewById(R.id.image_preview)); mTextPreview = requireNonNull(mView.findViewById(R.id.text_preview)); mEditChip = requireNonNull(mView.findViewById(R.id.edit_chip)); Loading @@ -143,7 +159,7 @@ public class ClipboardOverlayController { mDismissButton = requireNonNull(mView.findViewById(R.id.dismiss_button)); mView.setOnDismissCallback(this::hideImmediate); mView.setOnInteractionCallback(() -> mTimeoutHandler.resetTimeout()); mView.setOnInteractionCallback(mTimeoutHandler::resetTimeout); mDismissButton.setOnClickListener(view -> animateOut()); Loading @@ -166,7 +182,7 @@ public class ClipboardOverlayController { withWindowAttached(() -> { mWindow.setContentView(mView); updateInsets(mWindowManager.getCurrentWindowMetrics().getWindowInsets()); mView.post(() -> getEnterAnimation().start()); mView.post(this::animateIn); }); mTimeoutHandler.setOnTimeoutRunnable(this::animateOut); Loading Loading @@ -199,12 +215,15 @@ public class ClipboardOverlayController { void setClipData(ClipData clipData) { reset(); if (clipData == null || clipData.getItemCount() == 0) { showTextPreview( mContext.getResources().getString(R.string.clipboard_overlay_text_copied)); showTextPreview(mContext.getResources().getString( R.string.clipboard_overlay_text_copied)); } else if (!TextUtils.isEmpty(clipData.getItemAt(0).getText())) { showEditableText(clipData.getItemAt(0).getText()); ClipData.Item item = clipData.getItemAt(0); if (item.getTextLinks() != null) { AsyncTask.execute(() -> classifyText(clipData.getItemAt(0))); } showEditableText(item.getText()); } else if (clipData.getItemAt(0).getUri() != null) { // How to handle non-image URIs? showEditableImage(clipData.getItemAt(0).getUri()); Loading @@ -212,7 +231,6 @@ public class ClipboardOverlayController { showTextPreview( mContext.getResources().getString(R.string.clipboard_overlay_text_copied)); } mTimeoutHandler.resetTimeout(); } Loading @@ -220,10 +238,40 @@ public class ClipboardOverlayController { mOnSessionCompleteListener = runnable; } private void classifyText(ClipData.Item item) { ArrayList<RemoteAction> actions = new ArrayList<>(); for (TextLinks.TextLink link : item.getTextLinks().getLinks()) { TextClassification classification = mTextClassifier.classifyText( item.getText(), link.getStart(), link.getEnd(), null); actions.addAll(classification.getActions()); } mView.post(() -> { for (ScreenshotActionChip chip : mActionChips) { mActionContainer.removeView(chip); } mActionChips.clear(); for (RemoteAction action : actions) { ScreenshotActionChip chip = constructActionChip(action); mActionContainer.addView(chip); mActionChips.add(chip); } }); } private ScreenshotActionChip constructActionChip(RemoteAction action) { ScreenshotActionChip chip = (ScreenshotActionChip) LayoutInflater.from(mContext).inflate( R.layout.screenshot_action_chip, mActionContainer, false); chip.setText(action.getTitle()); chip.setIcon(action.getIcon(), false); chip.setPendingIntent(action.getActionIntent(), this::animateOut); chip.setAlpha(1); return chip; } private void monitorOutsideTouches() { InputManager inputManager = mContext.getSystemService(InputManager.class); InputMonitor monitor = inputManager.monitorGestureInput("clipboard overlay", 0); mInputEventReceiver = new InputEventReceiver(monitor.getInputChannel(), mInputMonitor = inputManager.monitorGestureInput("clipboard overlay", 0); mInputEventReceiver = new InputEventReceiver(mInputMonitor.getInputChannel(), Looper.getMainLooper()) { @Override public void onInputEvent(InputEvent event) { Loading Loading @@ -311,6 +359,10 @@ public class ClipboardOverlayController { return nearbyIntent; } private void animateIn() { getEnterAnimation().start(); } private void animateOut() { getExitAnimation().start(); } Loading Loading @@ -390,6 +442,10 @@ public class ClipboardOverlayController { mInputEventReceiver.dispose(); mInputEventReceiver = null; } if (mInputMonitor != null) { mInputMonitor.dispose(); mInputMonitor = null; } if (mOnSessionCompleteListener != null) { mOnSessionCompleteListener.run(); } Loading @@ -398,6 +454,10 @@ public class ClipboardOverlayController { private void reset() { mView.setTranslationX(0); mView.setAlpha(0); for (ScreenshotActionChip chip : mActionChips) { mActionContainer.removeView(chip); } mActionChips.clear(); mTimeoutHandler.cancelTimeout(); } Loading packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java +0 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.content.Context; import android.graphics.drawable.Icon; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; Loading Loading @@ -129,7 +128,6 @@ public class ScreenshotActionChip extends FrameLayout { iconParams.setMarginStart(paddingHorizontal); iconParams.setMarginEnd(paddingHorizontal); } mTextView.setVisibility(hasText ? View.VISIBLE : View.GONE); mIconView.setLayoutParams(iconParams); mTextView.setLayoutParams(textParams); } Loading Loading
packages/SystemUI/res/layout/clipboard_overlay.xml +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ <com.android.systemui.clipboardoverlay.DraggableConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:alpha="0" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +2 −2 Original line number Diff line number Diff line Loading @@ -60,8 +60,8 @@ public class ClipboardListener extends CoreStartable return; } if (mClipboardOverlayController == null) { mClipboardOverlayController = new ClipboardOverlayController(mContext, new TimeoutHandler(mContext)); mClipboardOverlayController = new ClipboardOverlayController(mContext, new TimeoutHandler(mContext)); } mClipboardOverlayController.setClipData(mClipboardManager.getPrimaryClip()); mClipboardOverlayController.setOnSessionCompleteListener(() -> { Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java +71 −11 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.MainThread; import android.app.RemoteAction; import android.content.BroadcastReceiver; import android.content.ClipData; import android.content.ComponentName; Loading @@ -43,6 +44,7 @@ import android.graphics.drawable.Icon; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Looper; import android.text.TextUtils; import android.util.Log; Loading @@ -60,8 +62,13 @@ import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.policy.PhoneWindow; Loading @@ -71,6 +78,7 @@ import com.android.systemui.screenshot.ScreenshotActionChip; import com.android.systemui.screenshot.TimeoutHandler; import java.io.IOException; import java.util.ArrayList; /** * Controls state and UI for the overlay that appears when something is added to the clipboard Loading @@ -93,6 +101,7 @@ public class ClipboardOverlayController { private final PhoneWindow mWindow; private final TimeoutHandler mTimeoutHandler; private final AccessibilityManager mAccessibilityManager; private final TextClassifier mTextClassifier; private final DraggableConstraintLayout mView; private final ImageView mImagePreview; Loading @@ -101,9 +110,13 @@ public class ClipboardOverlayController { private final ScreenshotActionChip mRemoteCopyChip; private final View mActionContainerBackground; private final View mDismissButton; private final LinearLayout mActionContainer; private final ArrayList<ScreenshotActionChip> mActionChips = new ArrayList<>(); private Runnable mOnSessionCompleteListener; private InputMonitor mInputMonitor; private InputEventReceiver mInputEventReceiver; private BroadcastReceiver mCloseDialogsReceiver; Loading @@ -117,6 +130,8 @@ public class ClipboardOverlayController { mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null); mAccessibilityManager = AccessibilityManager.getInstance(mContext); mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class)) .getTextClassifier(); mWindowManager = mContext.getSystemService(WindowManager.class); Loading @@ -134,8 +149,9 @@ public class ClipboardOverlayController { mView = (DraggableConstraintLayout) LayoutInflater.from(mContext).inflate(R.layout.clipboard_overlay, null); mActionContainerBackground = requireNonNull( mView.findViewById(R.id.actions_container_background)); mActionContainerBackground = requireNonNull(mView.findViewById(R.id.actions_container_background)); mActionContainer = requireNonNull(mView.findViewById(R.id.actions)); mImagePreview = requireNonNull(mView.findViewById(R.id.image_preview)); mTextPreview = requireNonNull(mView.findViewById(R.id.text_preview)); mEditChip = requireNonNull(mView.findViewById(R.id.edit_chip)); Loading @@ -143,7 +159,7 @@ public class ClipboardOverlayController { mDismissButton = requireNonNull(mView.findViewById(R.id.dismiss_button)); mView.setOnDismissCallback(this::hideImmediate); mView.setOnInteractionCallback(() -> mTimeoutHandler.resetTimeout()); mView.setOnInteractionCallback(mTimeoutHandler::resetTimeout); mDismissButton.setOnClickListener(view -> animateOut()); Loading @@ -166,7 +182,7 @@ public class ClipboardOverlayController { withWindowAttached(() -> { mWindow.setContentView(mView); updateInsets(mWindowManager.getCurrentWindowMetrics().getWindowInsets()); mView.post(() -> getEnterAnimation().start()); mView.post(this::animateIn); }); mTimeoutHandler.setOnTimeoutRunnable(this::animateOut); Loading Loading @@ -199,12 +215,15 @@ public class ClipboardOverlayController { void setClipData(ClipData clipData) { reset(); if (clipData == null || clipData.getItemCount() == 0) { showTextPreview( mContext.getResources().getString(R.string.clipboard_overlay_text_copied)); showTextPreview(mContext.getResources().getString( R.string.clipboard_overlay_text_copied)); } else if (!TextUtils.isEmpty(clipData.getItemAt(0).getText())) { showEditableText(clipData.getItemAt(0).getText()); ClipData.Item item = clipData.getItemAt(0); if (item.getTextLinks() != null) { AsyncTask.execute(() -> classifyText(clipData.getItemAt(0))); } showEditableText(item.getText()); } else if (clipData.getItemAt(0).getUri() != null) { // How to handle non-image URIs? showEditableImage(clipData.getItemAt(0).getUri()); Loading @@ -212,7 +231,6 @@ public class ClipboardOverlayController { showTextPreview( mContext.getResources().getString(R.string.clipboard_overlay_text_copied)); } mTimeoutHandler.resetTimeout(); } Loading @@ -220,10 +238,40 @@ public class ClipboardOverlayController { mOnSessionCompleteListener = runnable; } private void classifyText(ClipData.Item item) { ArrayList<RemoteAction> actions = new ArrayList<>(); for (TextLinks.TextLink link : item.getTextLinks().getLinks()) { TextClassification classification = mTextClassifier.classifyText( item.getText(), link.getStart(), link.getEnd(), null); actions.addAll(classification.getActions()); } mView.post(() -> { for (ScreenshotActionChip chip : mActionChips) { mActionContainer.removeView(chip); } mActionChips.clear(); for (RemoteAction action : actions) { ScreenshotActionChip chip = constructActionChip(action); mActionContainer.addView(chip); mActionChips.add(chip); } }); } private ScreenshotActionChip constructActionChip(RemoteAction action) { ScreenshotActionChip chip = (ScreenshotActionChip) LayoutInflater.from(mContext).inflate( R.layout.screenshot_action_chip, mActionContainer, false); chip.setText(action.getTitle()); chip.setIcon(action.getIcon(), false); chip.setPendingIntent(action.getActionIntent(), this::animateOut); chip.setAlpha(1); return chip; } private void monitorOutsideTouches() { InputManager inputManager = mContext.getSystemService(InputManager.class); InputMonitor monitor = inputManager.monitorGestureInput("clipboard overlay", 0); mInputEventReceiver = new InputEventReceiver(monitor.getInputChannel(), mInputMonitor = inputManager.monitorGestureInput("clipboard overlay", 0); mInputEventReceiver = new InputEventReceiver(mInputMonitor.getInputChannel(), Looper.getMainLooper()) { @Override public void onInputEvent(InputEvent event) { Loading Loading @@ -311,6 +359,10 @@ public class ClipboardOverlayController { return nearbyIntent; } private void animateIn() { getEnterAnimation().start(); } private void animateOut() { getExitAnimation().start(); } Loading Loading @@ -390,6 +442,10 @@ public class ClipboardOverlayController { mInputEventReceiver.dispose(); mInputEventReceiver = null; } if (mInputMonitor != null) { mInputMonitor.dispose(); mInputMonitor = null; } if (mOnSessionCompleteListener != null) { mOnSessionCompleteListener.run(); } Loading @@ -398,6 +454,10 @@ public class ClipboardOverlayController { private void reset() { mView.setTranslationX(0); mView.setAlpha(0); for (ScreenshotActionChip chip : mActionChips) { mActionContainer.removeView(chip); } mActionChips.clear(); mTimeoutHandler.cancelTimeout(); } Loading
packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java +0 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.content.Context; import android.graphics.drawable.Icon; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; Loading Loading @@ -129,7 +128,6 @@ public class ScreenshotActionChip extends FrameLayout { iconParams.setMarginStart(paddingHorizontal); iconParams.setMarginEnd(paddingHorizontal); } mTextView.setVisibility(hasText ? View.VISIBLE : View.GONE); mIconView.setLayoutParams(iconParams); mTextView.setLayoutParams(textParams); } Loading