StackBox.java revision c00204b4d14d49a0417b44ca21aee4f0d4c466e0
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
19import android.graphics.Rect;
20
21public class StackBox {
22    /** For use with {@link WindowManagerService#createStack} */
23    public static final int TASK_STACK_GOES_BEFORE = 0;
24    public static final int TASK_STACK_GOES_AFTER = 1;
25    public static final int TASK_STACK_GOES_ABOVE = 2;
26    public static final int TASK_STACK_GOES_BELOW = 3;
27    public static final int TASK_STACK_GOES_OVER = 4;
28    public static final int TASK_STACK_GOES_UNDER = 5;
29
30    final DisplayContent mDisplayContent;
31    StackBox mParent;
32    boolean mVertical;
33    StackBox mFirst;
34    StackBox mSecond;
35    float mWeight;
36    TaskStack mStack;
37    Rect mBounds;
38    boolean layoutNeeded;
39
40    StackBox(DisplayContent displayContent, Rect bounds) {
41        mDisplayContent = displayContent;
42        mBounds = bounds;
43    }
44
45    /** Propagate #layoutNeeded bottom up. */
46    void makeDirty() {
47        layoutNeeded = true;
48        if (mParent != null) {
49            mParent.makeDirty();
50        }
51    }
52
53    /** Propagate #layoutNeeded top down. */
54    void makeClean() {
55        layoutNeeded = false;
56        if (mFirst != null) {
57            mFirst.makeClean();
58            mSecond.makeClean();
59        }
60    }
61
62    TaskStack split(int stackId, int relativeStackId, int position, float weight) {
63        if (mStack != null) {
64            if (mStack.mStackId == relativeStackId) {
65                // Found it!
66                TaskStack stack = new TaskStack(stackId, this);
67                TaskStack firstStack;
68                TaskStack secondStack;
69                int width, height, split;
70                switch (position) {
71                    default:
72                    case TASK_STACK_GOES_BEFORE:
73                    case TASK_STACK_GOES_AFTER:
74                        mVertical = false;
75                        width = (int)(weight * mBounds.width());
76                        height = mBounds.height();
77                        if (position == TASK_STACK_GOES_BEFORE) {
78                            firstStack = stack;
79                            secondStack = mStack;
80                            split = mBounds.left + width;
81                        } else {
82                            firstStack = mStack;
83                            secondStack = stack;
84                            split = mBounds.right - width;
85                        }
86                        break;
87                    case TASK_STACK_GOES_ABOVE:
88                    case TASK_STACK_GOES_BELOW:
89                        mVertical = true;
90                        width = mBounds.width();
91                        height = (int)(weight * mBounds.height());
92                        if (position == TASK_STACK_GOES_ABOVE) {
93                            firstStack = stack;
94                            secondStack = mStack;
95                            split = mBounds.top + height;
96                        } else {
97                            firstStack = mStack;
98                            secondStack = stack;
99                            split = mBounds.bottom - height;
100                        }
101                        break;
102                }
103                mFirst = new StackBox(mDisplayContent, new Rect(mBounds.left, mBounds.top,
104                        mVertical ? mBounds.right : split, mVertical ? split : mBounds.bottom));
105                mFirst.mStack = firstStack;
106                mSecond = new StackBox(mDisplayContent, new Rect(mVertical ? mBounds.left : split,
107                        mVertical ? split : mBounds.top, mBounds.right, mBounds.bottom));
108                mSecond.mStack = secondStack;
109                mStack = null;
110                return stack;
111            }
112            return null;
113        }
114
115        // Propagate the split to see if the target task stack is in either sub box.
116        TaskStack stack = mFirst.split(stackId, relativeStackId, position, weight);
117        if (stack != null) {
118            return stack;
119        }
120        return mSecond.split(stackId, relativeStackId, position, weight);
121    }
122
123    TaskStack merge(int position) {
124        TaskStack stack = null;
125        if (mFirst != null) {
126            switch (position) {
127                default:
128                case TASK_STACK_GOES_BEFORE:
129                case TASK_STACK_GOES_ABOVE:
130                    stack = mFirst.merge(position);
131                    stack.merge(mSecond.merge(position));
132                    break;
133                case TASK_STACK_GOES_AFTER:
134                case TASK_STACK_GOES_BELOW:
135                    stack = mSecond.merge(position);
136                    stack.merge(mFirst.merge(position));
137                    break;
138            }
139            return stack;
140        }
141        return mStack;
142    }
143
144    boolean merge(int stackId, int position, StackBox primary, StackBox secondary) {
145        TaskStack stack = primary.mStack;
146        if (stack != null && stack.mStackId == stackId) {
147            stack.merge(secondary.merge(position));
148            mStack = stack;
149            mFirst = null;
150            mSecond = null;
151            return true;
152        }
153        return false;
154    }
155
156    boolean merge(int stackId, int position) {
157        if (mFirst != null) {
158            if (merge(stackId, position, mFirst, mSecond)
159                    || merge(stackId, position, mSecond, mFirst)
160                    || mFirst.merge(stackId, position)
161                    || mSecond.merge(stackId, position)) {
162                return true;
163            }
164        }
165        return false;
166    }
167
168    void absorb(StackBox box) {
169        mFirst = box.mFirst;
170        mSecond = box.mSecond;
171        mStack = box.mStack;
172        layoutNeeded = true;
173    }
174
175    void removeStack() {
176        if (mParent != null) {
177            if (mParent.mFirst == this) {
178                mParent.absorb(mParent.mSecond);
179            } else {
180                mParent.absorb(mParent.mFirst);
181            }
182            mParent.makeDirty();
183        }
184    }
185
186    boolean addTaskToStack(Task task, int stackId, boolean toTop) {
187        if (mStack != null) {
188            if (mStack.mStackId == stackId) {
189                mStack.addTask(task, toTop);
190                return true;
191            }
192            return false;
193        }
194        return mFirst.addTaskToStack(task, stackId, toTop)
195                || mSecond.addTaskToStack(task, stackId, toTop);
196    }
197
198    boolean resize(int stackId, float weight) {
199        return false;
200    }
201}
202