| /* |
| * 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); |
| } |
| } |