blob: f1f5fe88cc852d626bb2f78ce657c80a1baf34db [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.Slog;
import android.view.Display;
import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import com.android.server.wm.WindowStateAnimator.SurfaceTrace;
class FocusedStackFrame {
private static final String TAG = "FocusedStackFrame";
private static final int THICKNESS = 10;
private static final float ALPHA = 0.3f;
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
private final Rect mLastBounds = new Rect();
final Rect mBounds = new Rect();
private final Rect mTmpDrawRect = new Rect();
public FocusedStackFrame(Display display, SurfaceSession session) {
SurfaceControl ctrl = null;
try {
if (DEBUG_SURFACE_TRACE) {
ctrl = new SurfaceTrace(session, "FocusedStackFrame",
1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
} else {
ctrl = new SurfaceControl(session, "FocusedStackFrame",
1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
}
ctrl.setLayerStack(display.getLayerStack());
ctrl.setAlpha(ALPHA);
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
}
private void draw(Rect bounds, int color) {
if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() +
" color=" + Integer.toHexString(color));
mTmpDrawRect.set(bounds);
Canvas c = null;
try {
c = mSurface.lockCanvas(mTmpDrawRect);
} catch (IllegalArgumentException e) {
} catch (Surface.OutOfResourcesException e) {
}
if (c == null) {
return;
}
final int w = bounds.width();
final int h = bounds.height();
// Top
mTmpDrawRect.set(0, 0, w, THICKNESS);
c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
c.drawColor(color);
// Left (not including Top or Bottom stripe).
mTmpDrawRect.set(0, THICKNESS, THICKNESS, h - THICKNESS);
c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
c.drawColor(color);
// Right (not including Top or Bottom stripe).
mTmpDrawRect.set(w - THICKNESS, THICKNESS, w, h - THICKNESS);
c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
c.drawColor(color);
// Bottom
mTmpDrawRect.set(0, h - THICKNESS, w, h);
c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
c.drawColor(color);
mSurface.unlockCanvasAndPost(c);
}
private void positionSurface(Rect bounds) {
if (false && DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString());
mSurfaceControl.setSize(bounds.width(), bounds.height());
mSurfaceControl.setPosition(bounds.left, bounds.top);
}
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
public void setVisibility(boolean on) {
if (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on +
" mLastBounds=" + mLastBounds.toShortString() +
" mBounds=" + mBounds.toShortString());
if (mSurfaceControl == null) {
return;
}
if (on) {
if (!mLastBounds.equals(mBounds)) {
// Erase the previous rectangle.
positionSurface(mLastBounds);
draw(mLastBounds, Color.TRANSPARENT);
// Draw the latest rectangle.
positionSurface(mBounds);
draw(mBounds, Color.WHITE);
// Update the history.
mLastBounds.set(mBounds);
}
mSurfaceControl.show();
} else {
mSurfaceControl.hide();
}
}
public void setBounds(TaskStack stack) {
stack.getBounds(mBounds);
if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
}
public void setLayer(int layer) {
mSurfaceControl.setLayer(layer);
}
}