diff options
4 files changed, 187 insertions, 95 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 73bd521fd2f2..01187ed94de5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -22,13 +22,10 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.Color; import android.graphics.Point; import android.graphics.PointF; -import android.graphics.drawable.GradientDrawable; import android.os.Handler; import android.util.Log; import android.view.Choreographer; @@ -36,7 +33,6 @@ import android.view.MotionEvent; import android.view.SurfaceControl; import android.view.View; import android.view.ViewConfiguration; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; import android.window.WindowContainerTransaction; @@ -47,6 +43,9 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.desktopmode.DesktopTasksController; +import com.android.wm.shell.windowdecor.viewholder.DesktopModeAppControlsWindowDecorationViewHolder; +import com.android.wm.shell.windowdecor.viewholder.DesktopModeFocusedWindowDecorationViewHolder; +import com.android.wm.shell.windowdecor.viewholder.DesktopModeWindowDecorationViewHolder; /** * Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with @@ -61,6 +60,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private final Choreographer mChoreographer; private final SyncTransactionQueue mSyncQueue; + private DesktopModeWindowDecorationViewHolder mWindowDecorViewHolder; private View.OnClickListener mOnCaptionButtonClickListener; private View.OnTouchListener mOnCaptionTouchListener; private DragPositioningCallback mDragPositioningCallback; @@ -171,11 +171,24 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin return; } if (oldRootView != mResult.mRootView) { - setupRootView(); + if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_focused_window_decor) { + mWindowDecorViewHolder = new DesktopModeFocusedWindowDecorationViewHolder( + mResult.mRootView, + mOnCaptionTouchListener, + mOnCaptionButtonClickListener + ); + } else if (mRelayoutParams.mLayoutResId + == R.layout.desktop_mode_app_controls_window_decor) { + mWindowDecorViewHolder = new DesktopModeAppControlsWindowDecorationViewHolder( + mResult.mRootView, + mOnCaptionTouchListener, + mOnCaptionButtonClickListener + ); + } else { + throw new IllegalArgumentException("Unexpected layout resource id"); + } } - - updateAppInfo(); - setCaptionColor(taskInfo.taskDescription.getStatusBarColor()); + mWindowDecorViewHolder.bindData(mTaskInfo); if (!isDragResizeable) { closeDragResizeListener(); @@ -205,27 +218,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mResult.mWidth, mResult.mHeight, resize_handle, resize_corner, touchSlop); } - /** - * Sets up listeners when a new root view is created. - */ - private void setupRootView() { - final View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption); - caption.setOnTouchListener(mOnCaptionTouchListener); - final View handle = caption.findViewById(R.id.caption_handle); - handle.setOnTouchListener(mOnCaptionTouchListener); - if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_focused_window_decor) { - handle.setOnClickListener(mOnCaptionButtonClickListener); - } else if (mRelayoutParams.mLayoutResId - == R.layout.desktop_mode_app_controls_window_decor) { - caption.findViewById(R.id.open_menu_button) - .setOnClickListener(mOnCaptionButtonClickListener); - caption.findViewById(R.id.close_window) - .setOnClickListener(mOnCaptionButtonClickListener); - } else { - throw new IllegalArgumentException("Unexpected layout resource id"); - } - } - private void setupHandleMenu() { final View menu = mHandleMenu.mWindowViewHost.getView(); final View fullscreen = menu.findViewById(R.id.fullscreen_button); @@ -249,17 +241,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin loadAppInfo(appName, appIcon); } - private void updateAppInfo() { - if (mRelayoutParams.mLayoutResId - != R.layout.desktop_mode_app_controls_window_decor) { - // The app info views only apply to the app controls window decor type. - return; - } - final TextView appNameTextView = mResult.mRootView.findViewById(R.id.application_name); - final ImageView appIconImageView = mResult.mRootView.findViewById(R.id.application_icon); - loadAppInfo(appNameTextView, appIconImageView); - } - boolean isHandleMenuActive() { return mHandleMenu != null; } @@ -278,61 +259,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } } - private void setCaptionColor(int captionColor) { - if (mResult.mRootView == null) { - return; - } - - final View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption); - final GradientDrawable captionDrawable = (GradientDrawable) caption.getBackground(); - captionDrawable.setColor(captionColor); - - final boolean shouldUseLightCaptionViews = Color.valueOf(captionColor).luminance() < 0.5; - if (mRelayoutParams.mLayoutResId - == R.layout.desktop_mode_focused_window_decor) { - final ImageButton captionBar = caption.findViewById(R.id.caption_handle); - captionBar.setImageTintList(ColorStateList.valueOf( - getCaptionHandleBarColor(shouldUseLightCaptionViews))); - } else if (mRelayoutParams.mLayoutResId - == R.layout.desktop_mode_app_controls_window_decor) { - final ImageButton closeBtn = caption.findViewById(R.id.close_window); - final ImageButton expandBtn = caption.findViewById(R.id.expand_menu_button); - final TextView appNameTextView = caption.findViewById(R.id.application_name); - closeBtn.setImageTintList(ColorStateList.valueOf( - getCaptionCloseButtonColor(shouldUseLightCaptionViews))); - expandBtn.setImageTintList(ColorStateList.valueOf( - getCaptionExpandButtonColor(shouldUseLightCaptionViews))); - appNameTextView.setTextColor( - getCaptionAppNameTextColor(shouldUseLightCaptionViews)); - } else { - throw new IllegalArgumentException("Unexpected layout resource id"); - } - } - - private int getCaptionHandleBarColor(boolean shouldUseLightCaptionViews) { - return shouldUseLightCaptionViews - ? mContext.getColor(R.color.desktop_mode_caption_handle_bar_light) - : mContext.getColor(R.color.desktop_mode_caption_handle_bar_dark); - } - - private int getCaptionAppNameTextColor(boolean shouldUseLightCaptionViews) { - return shouldUseLightCaptionViews - ? mContext.getColor(R.color.desktop_mode_caption_app_name_light) - : mContext.getColor(R.color.desktop_mode_caption_app_name_dark); - } - - private int getCaptionCloseButtonColor(boolean shouldUseLightCaptionViews) { - return shouldUseLightCaptionViews - ? mContext.getColor(R.color.desktop_mode_caption_close_button_light) - : mContext.getColor(R.color.desktop_mode_caption_close_button_dark); - } - - private int getCaptionExpandButtonColor(boolean shouldUseLightCaptionViews) { - return shouldUseLightCaptionViews - ? mContext.getColor(R.color.desktop_mode_caption_expand_button_light) - : mContext.getColor(R.color.desktop_mode_caption_expand_button_dark); - } - private void closeDragResizeListener() { if (mDragResizeListener == null) { return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt new file mode 100644 index 000000000000..95b5051cb81d --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt @@ -0,0 +1,94 @@ +package com.android.wm.shell.windowdecor.viewholder + +import android.app.ActivityManager.RunningTaskInfo +import android.content.pm.PackageManager +import android.content.res.ColorStateList +import android.graphics.drawable.GradientDrawable +import android.util.Log +import android.view.View +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import com.android.wm.shell.R + +/** + * A desktop mode window decoration used when the window is floating (i.e. freeform). It hosts + * finer controls such as a close window button and an "app info" section to pull up additional + * controls. + */ +internal class DesktopModeAppControlsWindowDecorationViewHolder( + rootView: View, + onCaptionTouchListener: View.OnTouchListener, + onCaptionButtonClickListener: View.OnClickListener +) : DesktopModeWindowDecorationViewHolder(rootView) { + + private val captionView: View = rootView.findViewById(R.id.desktop_mode_caption) + private val captionHandle: View = rootView.findViewById(R.id.caption_handle) + private val openMenuButton: View = rootView.findViewById(R.id.open_menu_button) + private val closeWindowButton: ImageButton = rootView.findViewById(R.id.close_window) + private val expandMenuButton: ImageButton = rootView.findViewById(R.id.expand_menu_button) + private val appNameTextView: TextView = rootView.findViewById(R.id.application_name) + private val appIconImageView: ImageView = rootView.findViewById(R.id.application_icon) + + init { + captionView.setOnTouchListener(onCaptionTouchListener) + captionHandle.setOnTouchListener(onCaptionTouchListener) + openMenuButton.setOnClickListener(onCaptionButtonClickListener) + closeWindowButton.setOnClickListener(onCaptionButtonClickListener) + } + + override fun bindData(taskInfo: RunningTaskInfo) { + bindAppInfo(taskInfo) + + val captionDrawable = captionView.background as GradientDrawable + captionDrawable.setColor(taskInfo.taskDescription.statusBarColor) + + closeWindowButton.imageTintList = ColorStateList.valueOf( + getCaptionCloseButtonColor(taskInfo)) + expandMenuButton.imageTintList = ColorStateList.valueOf( + getCaptionExpandButtonColor(taskInfo)) + appNameTextView.setTextColor(getCaptionAppNameTextColor(taskInfo)) + } + + private fun bindAppInfo(taskInfo: RunningTaskInfo) { + val packageName: String = taskInfo.realActivity.packageName + val pm: PackageManager = context.applicationContext.packageManager + try { + // TODO(b/268363572): Use IconProvider or BaseIconCache to set drawable/name. + val applicationInfo = pm.getApplicationInfo(packageName, + PackageManager.ApplicationInfoFlags.of(0)) + appNameTextView.text = pm.getApplicationLabel(applicationInfo) + appIconImageView.setImageDrawable(pm.getApplicationIcon(applicationInfo)) + } catch (e: PackageManager.NameNotFoundException) { + Log.w(TAG, "Package not found: $packageName", e) + } + } + + private fun getCaptionAppNameTextColor(taskInfo: RunningTaskInfo): Int { + return if (shouldUseLightCaptionColors(taskInfo)) { + context.getColor(R.color.desktop_mode_caption_app_name_light) + } else { + context.getColor(R.color.desktop_mode_caption_app_name_dark) + } + } + + private fun getCaptionCloseButtonColor(taskInfo: RunningTaskInfo): Int { + return if (shouldUseLightCaptionColors(taskInfo)) { + context.getColor(R.color.desktop_mode_caption_close_button_light) + } else { + context.getColor(R.color.desktop_mode_caption_close_button_dark) + } + } + + private fun getCaptionExpandButtonColor(taskInfo: RunningTaskInfo): Int { + return if (shouldUseLightCaptionColors(taskInfo)) { + context.getColor(R.color.desktop_mode_caption_expand_button_light) + } else { + context.getColor(R.color.desktop_mode_caption_expand_button_dark) + } + } + + companion object { + private const val TAG = "DesktopModeAppControlsWindowDecorationViewHolder" + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt new file mode 100644 index 000000000000..47a12a0cb71c --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt @@ -0,0 +1,44 @@ +package com.android.wm.shell.windowdecor.viewholder + +import android.app.ActivityManager.RunningTaskInfo +import android.content.res.ColorStateList +import android.graphics.drawable.GradientDrawable +import android.view.View +import android.widget.ImageButton +import com.android.wm.shell.R + +/** + * A desktop mode window decoration used when the window is in full "focus" (i.e. fullscreen). It + * hosts a simple handle bar from which to initiate a drag motion to enter desktop mode. + */ +internal class DesktopModeFocusedWindowDecorationViewHolder( + rootView: View, + onCaptionTouchListener: View.OnTouchListener, + onCaptionButtonClickListener: View.OnClickListener +) : DesktopModeWindowDecorationViewHolder(rootView) { + + private val captionView: View = rootView.findViewById(R.id.desktop_mode_caption) + private val captionHandle: ImageButton = rootView.findViewById(R.id.caption_handle) + + init { + captionView.setOnTouchListener(onCaptionTouchListener) + captionHandle.setOnTouchListener(onCaptionTouchListener) + captionHandle.setOnClickListener(onCaptionButtonClickListener) + } + + override fun bindData(taskInfo: RunningTaskInfo) { + val captionColor = taskInfo.taskDescription.statusBarColor + val captionDrawable = captionView.background as GradientDrawable + captionDrawable.setColor(captionColor) + + captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo)) + } + + private fun getCaptionHandleBarColor(taskInfo: RunningTaskInfo): Int { + return if (shouldUseLightCaptionColors(taskInfo)) { + context.getColor(R.color.desktop_mode_caption_handle_bar_light) + } else { + context.getColor(R.color.desktop_mode_caption_handle_bar_dark) + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt new file mode 100644 index 000000000000..514ea52cb8ae --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt @@ -0,0 +1,28 @@ +package com.android.wm.shell.windowdecor.viewholder + +import android.app.ActivityManager.RunningTaskInfo +import android.content.Context +import android.graphics.Color +import android.view.View + +/** + * Encapsulates the root [View] of a window decoration and its children to facilitate looking up + * children (via findViewById) and updating to the latest data from [RunningTaskInfo]. + */ +internal abstract class DesktopModeWindowDecorationViewHolder(rootView: View) { + val context: Context = rootView.context + + /** + * A signal to the view holder that new data is available and that the views should be updated + * to reflect it. + */ + abstract fun bindData(taskInfo: RunningTaskInfo) + + /** + * Whether the caption items should use the 'light' color variant so that there's good contrast + * with the caption background color. + */ + protected fun shouldUseLightCaptionColors(taskInfo: RunningTaskInfo): Boolean { + return Color.valueOf(taskInfo.taskDescription.statusBarColor).luminance() < 0.5 + } +} |