Loading core/java/com/android/internal/widget/NonClientDecorView.java +75 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Rect; import android.os.RemoteException; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.view.ViewGroup; Loading Loading @@ -63,18 +64,31 @@ public class NonClientDecorView extends LinearLayout implements View.OnClickList private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20; // The height of a window which has not in DIP. private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5; private PhoneWindow mOwner = null; boolean mWindowHasShadow = false; boolean mShowDecor = false; private boolean mWindowHasShadow = false; private boolean mShowDecor = false; // True if the window is being dragged. private boolean mDragging = false; // The bounds of the window and the absolute mouse pointer coordinates from before we started to // drag the window. They will be used to determine the next window position. private final Rect mWindowOriginalBounds = new Rect(); private float mStartDragX; private float mStartDragY; // True when the left mouse button got released while dragging. private boolean mLeftMouseButtonReleased; // Avoiding re-creation of Rect's by keeping a temporary window drag bound. private final Rect mWindowDragBounds = new Rect(); // The current focus state of the window for updating the window elevation. boolean mWindowHasFocus = true; private boolean mWindowHasFocus = true; // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer // size calculation takes the shadow size into account. We set the elevation currently // to max until the first layout command has been executed. boolean mAllowUpdateElevation = false; private boolean mAllowUpdateElevation = false; public NonClientDecorView(Context context) { super(context); Loading Loading @@ -103,6 +117,62 @@ public class NonClientDecorView extends LinearLayout implements View.OnClickList findViewById(R.id.close_window).setOnClickListener(this); } @Override public boolean onTouchEvent(MotionEvent e) { // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch) // the old input device events get cancelled first. So no need to remember the kind of // input device we are listening to. switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: // A drag action is started if we aren't dragging already and the starting event is // either a left mouse button or any other input device. if (!mDragging && (e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE || (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0)) { mDragging = true; mWindowOriginalBounds.set(getActivityBounds()); mLeftMouseButtonReleased = false; mStartDragX = e.getRawX(); mStartDragY = e.getRawY(); } break; case MotionEvent.ACTION_MOVE: if (mDragging && !mLeftMouseButtonReleased) { if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE && (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) { // There is no separate mouse button up call and if the user mixes mouse // button drag actions, we stop dragging once he releases the button. mLeftMouseButtonReleased = true; break; } mWindowDragBounds.set(mWindowOriginalBounds); mWindowDragBounds.offset(Math.round(e.getRawX() - mStartDragX), Math.round(e.getRawY() - mStartDragY)); setActivityBounds(mWindowDragBounds); } break; case MotionEvent.ACTION_UP: if (mDragging) { // Since the window is already where it should be we don't have to do anything // special at this time. mDragging = false; return true; } break; case MotionEvent.ACTION_CANCEL: if (mDragging) { mDragging = false; setActivityBounds(mWindowOriginalBounds); return true; } break; } return mDragging; } /** * The phone window configuration has changed and the decor needs to be updated. * @param showDecor True if the decor should be shown. Loading services/core/java/com/android/server/wm/WindowState.java +59 −16 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; Loading @@ -38,6 +39,7 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.SystemClock; import android.os.WorkSource; import android.util.DisplayMetrics; import android.util.TimeUtils; import android.view.Display; import android.view.IWindowFocusObserver; Loading Loading @@ -78,6 +80,10 @@ class WindowList extends ArrayList<WindowState> { final class WindowState implements WindowManagerPolicy.WindowState { static final String TAG = "WindowState"; // The minimal size of a window within the usable area of the freeform stack. static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48; static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32; final WindowManagerService mService; final WindowManagerPolicy mPolicy; final Context mContext; Loading Loading @@ -536,6 +542,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mHaveFrame = true; final Task task = mAppToken != null ? getTask() : null; final boolean isFreeFormWorkspace = task != null && task.mStack != null && task.mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID; final boolean nonFullscreenTask = task != null && !task.isFullscreen(); if (nonFullscreenTask) { task.getBounds(mContainingFrame); Loading @@ -545,11 +553,21 @@ final class WindowState implements WindowManagerPolicy.WindowState { // IME is up and obscuring this window. Adjust the window position so it is visible. mContainingFrame.top -= mContainingFrame.bottom - cf.bottom; } if (isFreeFormWorkspace) { // In free form mode we have only to set the rectangle if it wasn't set already. No // need to intersect it with the (visible) "content frame" since it is allowed to // be outside the visible desktop. if (mContainingFrame.isEmpty()) { mContainingFrame.set(cf); } } else { // Make sure the containing frame is within the content frame so we don't layout // resized window under screen decorations. if (!mContainingFrame.intersect(cf)) { mContainingFrame.set(cf); } } mDisplayFrame.set(mContainingFrame); } else { mContainingFrame.set(pf); Loading Loading @@ -652,6 +670,23 @@ final class WindowState implements WindowManagerPolicy.WindowState { // Make sure the content and visible frames are inside of the // final window frame. if (isFreeFormWorkspace && !mFrame.isEmpty()) { // Keep the frame out of the blocked system area, limit it in size to the content area // and make sure that there is always a minimum visible so that the user can drag it // into a usable area.. final int height = Math.min(mFrame.height(), mContentFrame.height()); final int width = Math.min(mContentFrame.width(), mFrame.width()); final int minVisibleHeight = calculatePixelFromDp(MINIMUM_VISIBLE_HEIGHT_IN_DP); final int minVisibleWidth = calculatePixelFromDp(MINIMUM_VISIBLE_WIDTH_IN_DP); final int top = Math.max(mContentFrame.top, Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight)); final int left = Math.max(mContentFrame.left + minVisibleWidth - width, Math.min(mFrame.left, mContentFrame.right - minVisibleWidth)); mFrame.set(left, top, left + width, top + height); mContentFrame.set(mFrame); mVisibleFrame.set(mContentFrame); mStableFrame.set(mContentFrame); } else { mContentFrame.set(Math.max(mContentFrame.left, mFrame.left), Math.max(mContentFrame.top, mFrame.top), Math.min(mContentFrame.right, mFrame.right), Loading @@ -666,6 +701,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { Math.max(mStableFrame.top, mFrame.top), Math.min(mStableFrame.right, mFrame.right), Math.min(mStableFrame.bottom, mFrame.bottom)); } mOverscanInsets.set(Math.max(mOverscanFrame.left - mFrame.left, 0), Math.max(mOverscanFrame.top - mFrame.top, 0), Loading Loading @@ -1577,6 +1613,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } private int calculatePixelFromDp(int dp) { final Configuration serviceConfig = mService.mCurConfiguration; // TODO(multidisplay): Update Dp to that of display stack is on. final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; return (int)(dp * density); } void dump(PrintWriter pw, String prefix, boolean dumpAll) { final TaskStack stack = getStack(); pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId()); Loading Loading
core/java/com/android/internal/widget/NonClientDecorView.java +75 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Rect; import android.os.RemoteException; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.view.ViewGroup; Loading Loading @@ -63,18 +64,31 @@ public class NonClientDecorView extends LinearLayout implements View.OnClickList private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20; // The height of a window which has not in DIP. private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5; private PhoneWindow mOwner = null; boolean mWindowHasShadow = false; boolean mShowDecor = false; private boolean mWindowHasShadow = false; private boolean mShowDecor = false; // True if the window is being dragged. private boolean mDragging = false; // The bounds of the window and the absolute mouse pointer coordinates from before we started to // drag the window. They will be used to determine the next window position. private final Rect mWindowOriginalBounds = new Rect(); private float mStartDragX; private float mStartDragY; // True when the left mouse button got released while dragging. private boolean mLeftMouseButtonReleased; // Avoiding re-creation of Rect's by keeping a temporary window drag bound. private final Rect mWindowDragBounds = new Rect(); // The current focus state of the window for updating the window elevation. boolean mWindowHasFocus = true; private boolean mWindowHasFocus = true; // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer // size calculation takes the shadow size into account. We set the elevation currently // to max until the first layout command has been executed. boolean mAllowUpdateElevation = false; private boolean mAllowUpdateElevation = false; public NonClientDecorView(Context context) { super(context); Loading Loading @@ -103,6 +117,62 @@ public class NonClientDecorView extends LinearLayout implements View.OnClickList findViewById(R.id.close_window).setOnClickListener(this); } @Override public boolean onTouchEvent(MotionEvent e) { // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch) // the old input device events get cancelled first. So no need to remember the kind of // input device we are listening to. switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: // A drag action is started if we aren't dragging already and the starting event is // either a left mouse button or any other input device. if (!mDragging && (e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE || (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0)) { mDragging = true; mWindowOriginalBounds.set(getActivityBounds()); mLeftMouseButtonReleased = false; mStartDragX = e.getRawX(); mStartDragY = e.getRawY(); } break; case MotionEvent.ACTION_MOVE: if (mDragging && !mLeftMouseButtonReleased) { if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE && (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) { // There is no separate mouse button up call and if the user mixes mouse // button drag actions, we stop dragging once he releases the button. mLeftMouseButtonReleased = true; break; } mWindowDragBounds.set(mWindowOriginalBounds); mWindowDragBounds.offset(Math.round(e.getRawX() - mStartDragX), Math.round(e.getRawY() - mStartDragY)); setActivityBounds(mWindowDragBounds); } break; case MotionEvent.ACTION_UP: if (mDragging) { // Since the window is already where it should be we don't have to do anything // special at this time. mDragging = false; return true; } break; case MotionEvent.ACTION_CANCEL: if (mDragging) { mDragging = false; setActivityBounds(mWindowOriginalBounds); return true; } break; } return mDragging; } /** * The phone window configuration has changed and the decor needs to be updated. * @param showDecor True if the decor should be shown. Loading
services/core/java/com/android/server/wm/WindowState.java +59 −16 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; Loading @@ -38,6 +39,7 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.SystemClock; import android.os.WorkSource; import android.util.DisplayMetrics; import android.util.TimeUtils; import android.view.Display; import android.view.IWindowFocusObserver; Loading Loading @@ -78,6 +80,10 @@ class WindowList extends ArrayList<WindowState> { final class WindowState implements WindowManagerPolicy.WindowState { static final String TAG = "WindowState"; // The minimal size of a window within the usable area of the freeform stack. static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48; static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32; final WindowManagerService mService; final WindowManagerPolicy mPolicy; final Context mContext; Loading Loading @@ -536,6 +542,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mHaveFrame = true; final Task task = mAppToken != null ? getTask() : null; final boolean isFreeFormWorkspace = task != null && task.mStack != null && task.mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID; final boolean nonFullscreenTask = task != null && !task.isFullscreen(); if (nonFullscreenTask) { task.getBounds(mContainingFrame); Loading @@ -545,11 +553,21 @@ final class WindowState implements WindowManagerPolicy.WindowState { // IME is up and obscuring this window. Adjust the window position so it is visible. mContainingFrame.top -= mContainingFrame.bottom - cf.bottom; } if (isFreeFormWorkspace) { // In free form mode we have only to set the rectangle if it wasn't set already. No // need to intersect it with the (visible) "content frame" since it is allowed to // be outside the visible desktop. if (mContainingFrame.isEmpty()) { mContainingFrame.set(cf); } } else { // Make sure the containing frame is within the content frame so we don't layout // resized window under screen decorations. if (!mContainingFrame.intersect(cf)) { mContainingFrame.set(cf); } } mDisplayFrame.set(mContainingFrame); } else { mContainingFrame.set(pf); Loading Loading @@ -652,6 +670,23 @@ final class WindowState implements WindowManagerPolicy.WindowState { // Make sure the content and visible frames are inside of the // final window frame. if (isFreeFormWorkspace && !mFrame.isEmpty()) { // Keep the frame out of the blocked system area, limit it in size to the content area // and make sure that there is always a minimum visible so that the user can drag it // into a usable area.. final int height = Math.min(mFrame.height(), mContentFrame.height()); final int width = Math.min(mContentFrame.width(), mFrame.width()); final int minVisibleHeight = calculatePixelFromDp(MINIMUM_VISIBLE_HEIGHT_IN_DP); final int minVisibleWidth = calculatePixelFromDp(MINIMUM_VISIBLE_WIDTH_IN_DP); final int top = Math.max(mContentFrame.top, Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight)); final int left = Math.max(mContentFrame.left + minVisibleWidth - width, Math.min(mFrame.left, mContentFrame.right - minVisibleWidth)); mFrame.set(left, top, left + width, top + height); mContentFrame.set(mFrame); mVisibleFrame.set(mContentFrame); mStableFrame.set(mContentFrame); } else { mContentFrame.set(Math.max(mContentFrame.left, mFrame.left), Math.max(mContentFrame.top, mFrame.top), Math.min(mContentFrame.right, mFrame.right), Loading @@ -666,6 +701,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { Math.max(mStableFrame.top, mFrame.top), Math.min(mStableFrame.right, mFrame.right), Math.min(mStableFrame.bottom, mFrame.bottom)); } mOverscanInsets.set(Math.max(mOverscanFrame.left - mFrame.left, 0), Math.max(mOverscanFrame.top - mFrame.top, 0), Loading Loading @@ -1577,6 +1613,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } private int calculatePixelFromDp(int dp) { final Configuration serviceConfig = mService.mCurConfiguration; // TODO(multidisplay): Update Dp to that of display stack is on. final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; return (int)(dp * density); } void dump(PrintWriter pw, String prefix, boolean dumpAll) { final TaskStack stack = getStack(); pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId()); Loading