Merge "Add handle menu to bar type window caption." into tm-qpr-dev am: e480be9300
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20198779 Change-Id: I4b10d88107a1cdf28ada84ba1aef4b115c7153ef Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32.0dp"
|
||||||
|
android:height="32.0dp"
|
||||||
|
android:viewportWidth="32.0"
|
||||||
|
android:viewportHeight="32.0"
|
||||||
|
>
|
||||||
|
<group android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5"
|
||||||
|
android:translateX="6.0"
|
||||||
|
android:translateY="6.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/black"
|
||||||
|
android:pathData="M5.958,37.708Q4.458,37.708 3.354,36.604Q2.25,35.5 2.25,34V18.292Q2.25,16.792 3.354,15.688Q4.458,14.583 5.958,14.583H9.5V5.958Q9.5,4.458 10.625,3.354Q11.75,2.25 13.208,2.25H34Q35.542,2.25 36.646,3.354Q37.75,4.458 37.75,5.958V21.667Q37.75,23.167 36.646,24.271Q35.542,25.375 34,25.375H30.5V34Q30.5,35.5 29.396,36.604Q28.292,37.708 26.792,37.708ZM5.958,34H26.792Q26.792,34 26.792,34Q26.792,34 26.792,34V21.542H5.958V34Q5.958,34 5.958,34Q5.958,34 5.958,34ZM30.5,21.667H34Q34,21.667 34,21.667Q34,21.667 34,21.667V9.208H13.208V14.583H26.833Q28.375,14.583 29.438,15.667Q30.5,16.75 30.5,18.25Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32.0dp"
|
||||||
|
android:height="32.0dp"
|
||||||
|
android:viewportWidth="32.0"
|
||||||
|
android:viewportHeight="32.0"
|
||||||
|
>
|
||||||
|
<group android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5"
|
||||||
|
android:translateX="6.0"
|
||||||
|
android:translateY="6.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/black"
|
||||||
|
android:pathData="M18.167,21.875H29.833V10.208H18.167ZM7.875,35.833Q6.375,35.833 5.271,34.729Q4.167,33.625 4.167,32.125V7.875Q4.167,6.375 5.271,5.271Q6.375,4.167 7.875,4.167H32.125Q33.625,4.167 34.729,5.271Q35.833,6.375 35.833,7.875V32.125Q35.833,33.625 34.729,34.729Q33.625,35.833 32.125,35.833ZM7.875,32.125H32.125Q32.125,32.125 32.125,32.125Q32.125,32.125 32.125,32.125V7.875Q32.125,7.875 32.125,7.875Q32.125,7.875 32.125,7.875H7.875Q7.875,7.875 7.875,7.875Q7.875,7.875 7.875,7.875V32.125Q7.875,32.125 7.875,32.125Q7.875,32.125 7.875,32.125ZM7.875,7.875Q7.875,7.875 7.875,7.875Q7.875,7.875 7.875,7.875V32.125Q7.875,32.125 7.875,32.125Q7.875,32.125 7.875,32.125Q7.875,32.125 7.875,32.125Q7.875,32.125 7.875,32.125V7.875Q7.875,7.875 7.875,7.875Q7.875,7.875 7.875,7.875Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32.0dp"
|
||||||
|
android:height="32.0dp"
|
||||||
|
android:viewportWidth="32.0"
|
||||||
|
android:viewportHeight="32.0"
|
||||||
|
>
|
||||||
|
<group android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5"
|
||||||
|
android:translateX="6.0"
|
||||||
|
android:translateY="6.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/black"
|
||||||
|
android:pathData="M34.042,14.625V9.333Q34.042,9.333 34.042,9.333Q34.042,9.333 34.042,9.333H28.708V5.708H33.917Q35.458,5.708 36.562,6.833Q37.667,7.958 37.667,9.458V14.625ZM2.375,14.625V9.458Q2.375,7.958 3.479,6.833Q4.583,5.708 6.125,5.708H11.292V9.333H6Q6,9.333 6,9.333Q6,9.333 6,9.333V14.625ZM28.708,34.25V30.667H34.042Q34.042,30.667 34.042,30.667Q34.042,30.667 34.042,30.667V25.333H37.667V30.542Q37.667,32 36.562,33.125Q35.458,34.25 33.917,34.25ZM6.125,34.25Q4.583,34.25 3.479,33.125Q2.375,32 2.375,30.542V25.333H6V30.667Q6,30.667 6,30.667Q6,30.667 6,30.667H11.292V34.25ZM9.333,27.292V12.667H30.708V27.292ZM12.917,23.708H27.125V16.25H12.917ZM12.917,23.708V16.25V23.708Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32.0dp"
|
||||||
|
android:height="32.0dp"
|
||||||
|
android:viewportWidth="32.0"
|
||||||
|
android:viewportHeight="32.0"
|
||||||
|
>
|
||||||
|
<group android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5"
|
||||||
|
android:translateX="6.0"
|
||||||
|
android:translateY="6.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/black"
|
||||||
|
android:pathData="M8.083,22.833Q6.917,22.833 6.104,22Q5.292,21.167 5.292,20Q5.292,18.833 6.125,18Q6.958,17.167 8.125,17.167Q9.292,17.167 10.125,18Q10.958,18.833 10.958,20Q10.958,21.167 10.125,22Q9.292,22.833 8.083,22.833ZM20,22.833Q18.833,22.833 18,22Q17.167,21.167 17.167,20Q17.167,18.833 18,18Q18.833,17.167 20,17.167Q21.167,17.167 22,18Q22.833,18.833 22.833,20Q22.833,21.167 22,22Q21.167,22.833 20,22.833ZM31.875,22.833Q30.708,22.833 29.875,22Q29.042,21.167 29.042,20Q29.042,18.833 29.875,18Q30.708,17.167 31.917,17.167Q33.083,17.167 33.896,18Q34.708,18.833 34.708,20Q34.708,21.167 33.875,22Q33.042,22.833 31.875,22.833Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32.0dp"
|
||||||
|
android:height="32.0dp"
|
||||||
|
android:viewportWidth="32.0"
|
||||||
|
android:viewportHeight="32.0"
|
||||||
|
>
|
||||||
|
<group android:translateX="6.0"
|
||||||
|
android:translateY="8.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/black"
|
||||||
|
android:pathData="M18 14L13 14L13 2L18 2L18 14ZM20 14L20 2C20 0.9 19.1 -3.93402e-08 18 -8.74228e-08L13 -3.0598e-07C11.9 -3.54062e-07 11 0.9 11 2L11 14C11 15.1 11.9 16 13 16L18 16C19.1 16 20 15.1 20 14ZM7 14L2 14L2 2L7 2L7 14ZM9 14L9 2C9 0.9 8.1 -5.20166e-07 7 -5.68248e-07L2 -7.86805e-07C0.9 -8.34888e-07 -3.93403e-08 0.9 -8.74228e-08 2L-6.11959e-07 14C-6.60042e-07 15.1 0.9 16 2 16L7 16C8.1 16 9 15.1 9 14Z"/> </group>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="210.0dp"
|
||||||
|
android:height="64.0dp"
|
||||||
|
android:tint="@color/decor_button_light_color"
|
||||||
|
>
|
||||||
|
<group android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5"
|
||||||
|
android:translateX="8.0"
|
||||||
|
android:translateY="8.0" >
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M18.3334 14L13.3334 14L13.3334 2L18.3334 2L18.3334 14ZM20.3334 14L20.3334 2C20.3334 0.9 19.4334 -3.93402e-08 18.3334 -8.74228e-08L13.3334 -3.0598e-07C12.2334 -3.54062e-07 11.3334 0.9 11.3334 2L11.3334 14C11.3334 15.1 12.2334 16 13.3334 16L18.3334 16C19.4334 16 20.3334 15.1 20.3334 14ZM7.33337 14L2.33337 14L2.33337 2L7.33337 2L7.33337 14ZM9.33337 14L9.33337 2C9.33337 0.899999 8.43337 -5.20166e-07 7.33337 -5.68248e-07L2.33337 -7.86805e-07C1.23337 -8.34888e-07 0.333374 0.899999 0.333374 2L0.333373 14C0.333373 15.1 1.23337 16 2.33337 16L7.33337 16C8.43337 16 9.33337 15.1 9.33337 14Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
49
libs/WindowManager/Shell/res/layout/caption_handle_menu.xml
Normal file
49
libs/WindowManager/Shell/res/layout/caption_handle_menu.xml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<com.android.wm.shell.windowdecor.WindowDecorLinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/handle_menu"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:background="@drawable/decor_caption_title">
|
||||||
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
|
android:id="@+id/fullscreen_button"
|
||||||
|
android:contentDescription="@string/fullscreen_text"
|
||||||
|
android:background="@drawable/caption_fullscreen_button"/>
|
||||||
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
|
android:id="@+id/split_screen_button"
|
||||||
|
android:contentDescription="@string/split_screen_text"
|
||||||
|
android:background="@drawable/caption_split_screen_button"/>
|
||||||
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
|
android:id="@+id/floating_button"
|
||||||
|
android:contentDescription="@string/float_button_text"
|
||||||
|
android:background="@drawable/caption_floating_button"/>
|
||||||
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
|
android:id="@+id/desktop_button"
|
||||||
|
android:contentDescription="@string/desktop_text"
|
||||||
|
android:background="@drawable/caption_desktop_button"/>
|
||||||
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
|
android:id="@+id/more_button"
|
||||||
|
android:contentDescription="@string/more_button_text"
|
||||||
|
android:background="@drawable/caption_more_button"/>
|
||||||
|
</com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
|
||||||
@@ -19,14 +19,10 @@
|
|||||||
android:id="@+id/caption"
|
android:id="@+id/caption"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:background="@drawable/decor_caption_title">
|
android:background="@drawable/decor_caption_title">
|
||||||
<Button
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
android:id="@+id/back_button"
|
android:id="@+id/back_button"
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:contentDescription="@string/back_button_text"
|
android:contentDescription="@string/back_button_text"
|
||||||
android:background="@drawable/decor_back_button_dark"
|
android:background="@drawable/decor_back_button_dark"
|
||||||
/>
|
/>
|
||||||
@@ -39,11 +35,8 @@
|
|||||||
android:contentDescription="@string/handle_text"
|
android:contentDescription="@string/handle_text"
|
||||||
android:background="@drawable/decor_handle_dark"/>
|
android:background="@drawable/decor_handle_dark"/>
|
||||||
<Button
|
<Button
|
||||||
|
style="@style/CaptionButtonStyle"
|
||||||
android:id="@+id/close_window"
|
android:id="@+id/close_window"
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:contentDescription="@string/close_button_text"
|
android:contentDescription="@string/close_button_text"
|
||||||
android:background="@drawable/decor_close_button_dark"/>
|
android:background="@drawable/decor_close_button_dark"/>
|
||||||
</com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
|
</com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
|
||||||
@@ -197,4 +197,14 @@
|
|||||||
<string name="back_button_text">Back</string>
|
<string name="back_button_text">Back</string>
|
||||||
<!-- Accessibility text for the caption handle [CHAR LIMIT=NONE] -->
|
<!-- Accessibility text for the caption handle [CHAR LIMIT=NONE] -->
|
||||||
<string name="handle_text">Handle</string>
|
<string name="handle_text">Handle</string>
|
||||||
|
<!-- Accessibility text for the handle fullscreen button [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="fullscreen_text">Fullscreen</string>
|
||||||
|
<!-- Accessibility text for the handle desktop button [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="desktop_text">Desktop Mode</string>
|
||||||
|
<!-- Accessibility text for the handle split screen button [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="split_screen_text">Split Screen</string>
|
||||||
|
<!-- Accessibility text for the handle more options button [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="more_button_text">More</string>
|
||||||
|
<!-- Accessibility text for the handle floating window button [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="float_button_text">Float</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -30,6 +30,13 @@
|
|||||||
<item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
|
<item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="CaptionButtonStyle">
|
||||||
|
<item name="android:layout_width">32dp</item>
|
||||||
|
<item name="android:layout_height">32dp</item>
|
||||||
|
<item name="android:layout_margin">5dp</item>
|
||||||
|
<item name="android:padding">4dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="DockedDividerBackground">
|
<style name="DockedDividerBackground">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">@dimen/split_divider_bar_width</item>
|
<item name="android:layout_height">@dimen/split_divider_bar_width</item>
|
||||||
|
|||||||
@@ -26,11 +26,16 @@ import android.app.ActivityTaskManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
|
import android.view.InputChannel;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
|
import android.view.InputEvent;
|
||||||
|
import android.view.InputEventReceiver;
|
||||||
|
import android.view.InputMonitor;
|
||||||
import android.view.KeyCharacterMap;
|
import android.view.KeyCharacterMap;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@@ -64,8 +69,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
private final SyncTransactionQueue mSyncQueue;
|
private final SyncTransactionQueue mSyncQueue;
|
||||||
private FreeformTaskTransitionStarter mTransitionStarter;
|
private FreeformTaskTransitionStarter mTransitionStarter;
|
||||||
private DesktopModeController mDesktopModeController;
|
private DesktopModeController mDesktopModeController;
|
||||||
|
private EventReceiver mEventReceiver;
|
||||||
|
private InputMonitor mInputMonitor;
|
||||||
|
|
||||||
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
||||||
|
private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl();
|
||||||
|
|
||||||
public CaptionWindowDecorViewModel(
|
public CaptionWindowDecorViewModel(
|
||||||
Context context,
|
Context context,
|
||||||
@@ -108,12 +116,19 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
mSyncQueue);
|
mSyncQueue);
|
||||||
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
|
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
|
||||||
|
|
||||||
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration);
|
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration,
|
||||||
|
mDragStartListener);
|
||||||
CaptionTouchEventListener touchEventListener =
|
CaptionTouchEventListener touchEventListener =
|
||||||
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
||||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||||
windowDecoration.setDragResizeCallback(taskPositioner);
|
windowDecoration.setDragResizeCallback(taskPositioner);
|
||||||
setupWindowDecorationForTransition(taskInfo, startT, finishT);
|
setupWindowDecorationForTransition(taskInfo, startT, finishT);
|
||||||
|
if (mInputMonitor == null) {
|
||||||
|
mInputMonitor = InputManager.getInstance().monitorGestureInput(
|
||||||
|
"caption-touch", mContext.getDisplayId());
|
||||||
|
mEventReceiver = new EventReceiver(
|
||||||
|
mInputMonitor.getInputChannel(), Looper.myLooper());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +180,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
|
||||||
final int id = v.getId();
|
final int id = v.getId();
|
||||||
if (id == R.id.close_window) {
|
if (id == R.id.close_window) {
|
||||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
@@ -176,6 +192,15 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
}
|
}
|
||||||
} else if (id == R.id.back_button) {
|
} else if (id == R.id.back_button) {
|
||||||
injectBackKey();
|
injectBackKey();
|
||||||
|
} else if (id == R.id.caption_handle) {
|
||||||
|
decoration.createHandleMenu();
|
||||||
|
} else if (id == R.id.desktop_button) {
|
||||||
|
mDesktopModeController.setDesktopModeActive(true);
|
||||||
|
decoration.closeHandleMenu();
|
||||||
|
} else if (id == R.id.fullscreen_button) {
|
||||||
|
mDesktopModeController.setDesktopModeActive(false);
|
||||||
|
decoration.closeHandleMenu();
|
||||||
|
decoration.setButtonVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void injectBackKey() {
|
private void injectBackKey() {
|
||||||
@@ -257,6 +282,36 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InputEventReceiver to listen for touch input outside of caption bounds
|
||||||
|
private class EventReceiver extends InputEventReceiver {
|
||||||
|
EventReceiver(InputChannel channel, Looper looper) {
|
||||||
|
super(channel, looper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputEvent(InputEvent event) {
|
||||||
|
boolean handled = false;
|
||||||
|
if (event instanceof MotionEvent
|
||||||
|
&& ((MotionEvent) event).getActionMasked() == MotionEvent.ACTION_UP) {
|
||||||
|
handled = true;
|
||||||
|
CaptionWindowDecorViewModel.this.handleMotionEvent((MotionEvent) event);
|
||||||
|
}
|
||||||
|
finishInputEvent(event, handled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any input received is outside of caption bounds, turn off handle menu
|
||||||
|
private void handleMotionEvent(MotionEvent ev) {
|
||||||
|
int size = mWindowDecorByTaskId.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
CaptionWindowDecoration decoration = mWindowDecorByTaskId.valueAt(i);
|
||||||
|
if (decoration != null) {
|
||||||
|
decoration.closeHandleMenuIfNeeded(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
|
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
|
||||||
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
|
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
|
||||||
return DesktopModeStatus.IS_SUPPORTED
|
return DesktopModeStatus.IS_SUPPORTED
|
||||||
@@ -264,4 +319,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
|||||||
&& mDisplayController.getDisplayContext(taskInfo.displayId)
|
&& mDisplayController.getDisplayContext(taskInfo.displayId)
|
||||||
.getResources().getConfiguration().smallestScreenWidthDp >= 600;
|
.getResources().getConfiguration().smallestScreenWidthDp >= 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DragStartListenerImpl implements TaskPositioner.DragStartListener{
|
||||||
|
@Override
|
||||||
|
public void onDragStart(int taskId) {
|
||||||
|
mWindowDecorByTaskId.get(taskId).closeHandleMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,14 @@ import android.app.ActivityManager;
|
|||||||
import android.app.WindowConfiguration;
|
import android.app.WindowConfiguration;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
@@ -58,6 +62,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
|
|
||||||
private boolean mDesktopActive;
|
private boolean mDesktopActive;
|
||||||
|
|
||||||
|
private AdditionalWindow mHandleMenu;
|
||||||
|
|
||||||
CaptionWindowDecoration(
|
CaptionWindowDecoration(
|
||||||
Context context,
|
Context context,
|
||||||
DisplayController displayController,
|
DisplayController displayController,
|
||||||
@@ -123,7 +129,20 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
if (isDragResizeable) {
|
if (isDragResizeable) {
|
||||||
mRelayoutParams.setOutsets(outsetLeftId, outsetTopId, outsetRightId, outsetBottomId);
|
mRelayoutParams.setOutsets(outsetLeftId, outsetTopId, outsetRightId, outsetBottomId);
|
||||||
}
|
}
|
||||||
|
final Resources resources = mDecorWindowContext.getResources();
|
||||||
|
final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
|
||||||
|
final int captionHeight = loadDimensionPixelSize(resources,
|
||||||
|
mRelayoutParams.mCaptionHeightId);
|
||||||
|
final int captionWidth = loadDimensionPixelSize(resources,
|
||||||
|
mRelayoutParams.mCaptionWidthId);
|
||||||
|
final int captionLeft = taskBounds.width() / 2
|
||||||
|
- captionWidth / 2;
|
||||||
|
final int captionTop = taskBounds.top
|
||||||
|
<= captionHeight / 2 ? 0 : -captionHeight / 2;
|
||||||
|
mRelayoutParams.setCaptionPosition(captionLeft, captionTop);
|
||||||
|
|
||||||
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
|
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
|
||||||
|
taskInfo = null; // Clear it just in case we use it accidentally
|
||||||
|
|
||||||
mTaskOrganizer.applyTransaction(wct);
|
mTaskOrganizer.applyTransaction(wct);
|
||||||
|
|
||||||
@@ -137,15 +156,14 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this task is not focused, do not show caption.
|
// If this task is not focused, do not show caption.
|
||||||
setCaptionVisibility(taskInfo.isFocused);
|
setCaptionVisibility(mTaskInfo.isFocused);
|
||||||
|
|
||||||
// Only handle should show if Desktop Mode is inactive.
|
// Only handle should show if Desktop Mode is inactive.
|
||||||
boolean desktopCurrentStatus = DesktopModeStatus.isActive(mContext);
|
boolean desktopCurrentStatus = DesktopModeStatus.isActive(mContext);
|
||||||
if (mDesktopActive != desktopCurrentStatus && taskInfo.isFocused) {
|
if (mDesktopActive != desktopCurrentStatus && mTaskInfo.isFocused) {
|
||||||
mDesktopActive = desktopCurrentStatus;
|
mDesktopActive = desktopCurrentStatus;
|
||||||
setButtonVisibility();
|
setButtonVisibility();
|
||||||
}
|
}
|
||||||
taskInfo = null; // Clear it just in case we use it accidentally
|
|
||||||
|
|
||||||
if (!isDragResizeable) {
|
if (!isDragResizeable) {
|
||||||
closeDragResizeListener();
|
closeDragResizeListener();
|
||||||
@@ -184,9 +202,22 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
back.setOnClickListener(mOnCaptionButtonClickListener);
|
back.setOnClickListener(mOnCaptionButtonClickListener);
|
||||||
View handle = caption.findViewById(R.id.caption_handle);
|
View handle = caption.findViewById(R.id.caption_handle);
|
||||||
handle.setOnTouchListener(mOnCaptionTouchListener);
|
handle.setOnTouchListener(mOnCaptionTouchListener);
|
||||||
|
handle.setOnClickListener(mOnCaptionButtonClickListener);
|
||||||
setButtonVisibility();
|
setButtonVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupHandleMenu() {
|
||||||
|
View menu = mHandleMenu.mWindowViewHost.getView();
|
||||||
|
View fullscreen = menu.findViewById(R.id.fullscreen_button);
|
||||||
|
fullscreen.setOnClickListener(mOnCaptionButtonClickListener);
|
||||||
|
View desktop = menu.findViewById(R.id.desktop_button);
|
||||||
|
desktop.setOnClickListener(mOnCaptionButtonClickListener);
|
||||||
|
View split = menu.findViewById(R.id.split_screen_button);
|
||||||
|
split.setOnClickListener(mOnCaptionButtonClickListener);
|
||||||
|
View more = menu.findViewById(R.id.more_button);
|
||||||
|
more.setOnClickListener(mOnCaptionButtonClickListener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets caption visibility based on task focus.
|
* Sets caption visibility based on task focus.
|
||||||
*
|
*
|
||||||
@@ -194,8 +225,9 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
*/
|
*/
|
||||||
private void setCaptionVisibility(boolean visible) {
|
private void setCaptionVisibility(boolean visible) {
|
||||||
int v = visible ? View.VISIBLE : View.GONE;
|
int v = visible ? View.VISIBLE : View.GONE;
|
||||||
View caption = mResult.mRootView.findViewById(R.id.caption);
|
View captionView = mResult.mRootView.findViewById(R.id.caption);
|
||||||
caption.setVisibility(v);
|
captionView.setVisibility(v);
|
||||||
|
if (!visible) closeHandleMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,6 +235,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void setButtonVisibility() {
|
public void setButtonVisibility() {
|
||||||
|
mDesktopActive = DesktopModeStatus.isActive(mContext);
|
||||||
int v = mDesktopActive ? View.VISIBLE : View.GONE;
|
int v = mDesktopActive ? View.VISIBLE : View.GONE;
|
||||||
View caption = mResult.mRootView.findViewById(R.id.caption);
|
View caption = mResult.mRootView.findViewById(R.id.caption);
|
||||||
View back = caption.findViewById(R.id.back_button);
|
View back = caption.findViewById(R.id.back_button);
|
||||||
@@ -220,6 +253,10 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
caption.getBackground().setTint(v == View.VISIBLE ? Color.WHITE : Color.TRANSPARENT);
|
caption.getBackground().setTint(v == View.VISIBLE ? Color.WHITE : Color.TRANSPARENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHandleMenuActive() {
|
||||||
|
return mHandleMenu != null;
|
||||||
|
}
|
||||||
|
|
||||||
private void closeDragResizeListener() {
|
private void closeDragResizeListener() {
|
||||||
if (mDragResizeListener == null) {
|
if (mDragResizeListener == null) {
|
||||||
return;
|
return;
|
||||||
@@ -228,9 +265,67 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
mDragResizeListener = null;
|
mDragResizeListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and display handle menu window
|
||||||
|
*/
|
||||||
|
public void createHandleMenu() {
|
||||||
|
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||||
|
final Resources resources = mDecorWindowContext.getResources();
|
||||||
|
int x = mRelayoutParams.mCaptionX;
|
||||||
|
int y = mRelayoutParams.mCaptionY;
|
||||||
|
int width = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionWidthId);
|
||||||
|
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
|
||||||
|
String namePrefix = "Caption Menu";
|
||||||
|
mHandleMenu = addWindow(R.layout.caption_handle_menu, namePrefix, t,
|
||||||
|
x - mResult.mDecorContainerOffsetX, y - mResult.mDecorContainerOffsetY,
|
||||||
|
width, height);
|
||||||
|
mSyncQueue.runInSync(transaction -> {
|
||||||
|
transaction.merge(t);
|
||||||
|
t.close();
|
||||||
|
});
|
||||||
|
setupHandleMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the handle menu window
|
||||||
|
*/
|
||||||
|
public void closeHandleMenu() {
|
||||||
|
if (!isHandleMenuActive()) return;
|
||||||
|
mHandleMenu.releaseView();
|
||||||
|
mHandleMenu = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void releaseViews() {
|
||||||
|
closeHandleMenu();
|
||||||
|
super.releaseViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close an open handle menu if input is outside of menu coordinates
|
||||||
|
* @param ev the tapped point to compare against
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void closeHandleMenuIfNeeded(MotionEvent ev) {
|
||||||
|
if (mHandleMenu != null) {
|
||||||
|
Point positionInParent = mTaskOrganizer.getRunningTaskInfo(mTaskInfo.taskId)
|
||||||
|
.positionInParent;
|
||||||
|
final Resources resources = mDecorWindowContext.getResources();
|
||||||
|
ev.offsetLocation(-mRelayoutParams.mCaptionX, -mRelayoutParams.mCaptionY);
|
||||||
|
ev.offsetLocation(-positionInParent.x, -positionInParent.y);
|
||||||
|
int width = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionWidthId);
|
||||||
|
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
|
||||||
|
if (!(ev.getX() >= 0 && ev.getY() >= 0
|
||||||
|
&& ev.getX() <= width && ev.getY() <= height)) {
|
||||||
|
closeHandleMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
closeDragResizeListener();
|
closeDragResizeListener();
|
||||||
|
closeHandleMenu();
|
||||||
super.close();
|
super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,14 +42,18 @@ class TaskPositioner implements DragResizeCallback {
|
|||||||
private final Rect mResizeTaskBounds = new Rect();
|
private final Rect mResizeTaskBounds = new Rect();
|
||||||
|
|
||||||
private int mCtrlType;
|
private int mCtrlType;
|
||||||
|
private DragStartListener mDragStartListener;
|
||||||
|
|
||||||
TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration) {
|
TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
|
||||||
|
DragStartListener dragStartListener) {
|
||||||
mTaskOrganizer = taskOrganizer;
|
mTaskOrganizer = taskOrganizer;
|
||||||
mWindowDecoration = windowDecoration;
|
mWindowDecoration = windowDecoration;
|
||||||
|
mDragStartListener = dragStartListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDragResizeStart(int ctrlType, float x, float y) {
|
public void onDragResizeStart(int ctrlType, float x, float y) {
|
||||||
|
mDragStartListener.onDragStart(mWindowDecoration.mTaskInfo.taskId);
|
||||||
mCtrlType = ctrlType;
|
mCtrlType = ctrlType;
|
||||||
|
|
||||||
mTaskBoundsAtDragStart.set(
|
mTaskBoundsAtDragStart.set(
|
||||||
@@ -97,4 +101,12 @@ class TaskPositioner implements DragResizeCallback {
|
|||||||
mTaskOrganizer.applyTransaction(wct);
|
mTaskOrganizer.applyTransaction(wct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DragStartListener {
|
||||||
|
/**
|
||||||
|
* Inform the implementing class that a drag resize has started
|
||||||
|
* @param taskId id of this positioner's {@link WindowDecoration}
|
||||||
|
*/
|
||||||
|
void onDragStart(int taskId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,16 +200,17 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
|
|
||||||
final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
|
final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
|
||||||
final Resources resources = mDecorWindowContext.getResources();
|
final Resources resources = mDecorWindowContext.getResources();
|
||||||
final int decorContainerOffsetX = -loadDimensionPixelSize(resources, params.mOutsetLeftId);
|
outResult.mDecorContainerOffsetX = -loadDimensionPixelSize(resources, params.mOutsetLeftId);
|
||||||
final int decorContainerOffsetY = -loadDimensionPixelSize(resources, params.mOutsetTopId);
|
outResult.mDecorContainerOffsetY = -loadDimensionPixelSize(resources, params.mOutsetTopId);
|
||||||
outResult.mWidth = taskBounds.width()
|
outResult.mWidth = taskBounds.width()
|
||||||
+ loadDimensionPixelSize(resources, params.mOutsetRightId)
|
+ loadDimensionPixelSize(resources, params.mOutsetRightId)
|
||||||
- decorContainerOffsetX;
|
- outResult.mDecorContainerOffsetX;
|
||||||
outResult.mHeight = taskBounds.height()
|
outResult.mHeight = taskBounds.height()
|
||||||
+ loadDimensionPixelSize(resources, params.mOutsetBottomId)
|
+ loadDimensionPixelSize(resources, params.mOutsetBottomId)
|
||||||
- decorContainerOffsetY;
|
- outResult.mDecorContainerOffsetY;
|
||||||
startT.setPosition(
|
startT.setPosition(
|
||||||
mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY)
|
mDecorationContainerSurface,
|
||||||
|
outResult.mDecorContainerOffsetX, outResult.mDecorContainerOffsetY)
|
||||||
.setWindowCrop(mDecorationContainerSurface,
|
.setWindowCrop(mDecorationContainerSurface,
|
||||||
outResult.mWidth, outResult.mHeight)
|
outResult.mWidth, outResult.mHeight)
|
||||||
// TODO(b/244455401): Change the z-order when it's better organized
|
// TODO(b/244455401): Change the z-order when it's better organized
|
||||||
@@ -252,14 +253,11 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
|
final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
|
||||||
final int captionWidth = loadDimensionPixelSize(resources, params.mCaptionWidthId);
|
final int captionWidth = loadDimensionPixelSize(resources, params.mCaptionWidthId);
|
||||||
|
|
||||||
//Prevent caption from going offscreen if task is too high up
|
|
||||||
final int captionYPos = taskBounds.top <= captionHeight / 2 ? 0 : captionHeight / 2;
|
|
||||||
|
|
||||||
startT.setPosition(
|
startT.setPosition(
|
||||||
mCaptionContainerSurface, -decorContainerOffsetX
|
mCaptionContainerSurface,
|
||||||
+ taskBounds.width() / 2 - captionWidth / 2,
|
-outResult.mDecorContainerOffsetX + params.mCaptionX,
|
||||||
-decorContainerOffsetY - captionYPos)
|
-outResult.mDecorContainerOffsetY + params.mCaptionY)
|
||||||
.setWindowCrop(mCaptionContainerSurface, taskBounds.width(), captionHeight)
|
.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
|
||||||
.show(mCaptionContainerSurface);
|
.show(mCaptionContainerSurface);
|
||||||
|
|
||||||
if (mCaptionWindowManager == null) {
|
if (mCaptionWindowManager == null) {
|
||||||
@@ -292,7 +290,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
// Caption insets
|
// Caption insets
|
||||||
mCaptionInsetsRect.set(taskBounds);
|
mCaptionInsetsRect.set(taskBounds);
|
||||||
mCaptionInsetsRect.bottom =
|
mCaptionInsetsRect.bottom =
|
||||||
mCaptionInsetsRect.top + captionHeight - captionYPos;
|
mCaptionInsetsRect.top + captionHeight + params.mCaptionY;
|
||||||
wct.addRectInsetsProvider(mTaskInfo.token, mCaptionInsetsRect,
|
wct.addRectInsetsProvider(mTaskInfo.token, mCaptionInsetsRect,
|
||||||
CAPTION_INSETS_TYPES);
|
CAPTION_INSETS_TYPES);
|
||||||
} else {
|
} else {
|
||||||
@@ -302,10 +300,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
// Task surface itself
|
// Task surface itself
|
||||||
Point taskPosition = mTaskInfo.positionInParent;
|
Point taskPosition = mTaskInfo.positionInParent;
|
||||||
mTaskSurfaceCrop.set(
|
mTaskSurfaceCrop.set(
|
||||||
decorContainerOffsetX,
|
outResult.mDecorContainerOffsetX,
|
||||||
decorContainerOffsetY,
|
outResult.mDecorContainerOffsetY,
|
||||||
outResult.mWidth + decorContainerOffsetX,
|
outResult.mWidth + outResult.mDecorContainerOffsetX,
|
||||||
outResult.mHeight + decorContainerOffsetY);
|
outResult.mHeight + outResult.mDecorContainerOffsetY);
|
||||||
startT.show(mTaskSurface);
|
startT.show(mTaskSurface);
|
||||||
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
|
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
|
||||||
.setCrop(mTaskSurface, mTaskSurfaceCrop);
|
.setCrop(mTaskSurface, mTaskSurfaceCrop);
|
||||||
@@ -326,7 +324,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseViews() {
|
void releaseViews() {
|
||||||
if (mViewHost != null) {
|
if (mViewHost != null) {
|
||||||
mViewHost.release();
|
mViewHost.release();
|
||||||
mViewHost = null;
|
mViewHost = null;
|
||||||
@@ -369,20 +367,60 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
releaseViews();
|
releaseViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int loadDimensionPixelSize(Resources resources, int resourceId) {
|
static int loadDimensionPixelSize(Resources resources, int resourceId) {
|
||||||
if (resourceId == Resources.ID_NULL) {
|
if (resourceId == Resources.ID_NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return resources.getDimensionPixelSize(resourceId);
|
return resources.getDimensionPixelSize(resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float loadDimension(Resources resources, int resourceId) {
|
static float loadDimension(Resources resources, int resourceId) {
|
||||||
if (resourceId == Resources.ID_NULL) {
|
if (resourceId == Resources.ID_NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return resources.getDimension(resourceId);
|
return resources.getDimension(resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a window associated with this WindowDecoration.
|
||||||
|
* Note that subclass must dispose of this when the task is hidden/closed.
|
||||||
|
* @param layoutId layout to make the window from
|
||||||
|
* @param t the transaction to apply
|
||||||
|
* @param xPos x position of new window
|
||||||
|
* @param yPos y position of new window
|
||||||
|
* @param width width of new window
|
||||||
|
* @param height height of new window
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
AdditionalWindow addWindow(int layoutId, String namePrefix,
|
||||||
|
SurfaceControl.Transaction t, int xPos, int yPos, int width, int height) {
|
||||||
|
final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
|
||||||
|
SurfaceControl windowSurfaceControl = builder
|
||||||
|
.setName(namePrefix + " of Task=" + mTaskInfo.taskId)
|
||||||
|
.setContainerLayer()
|
||||||
|
.setParent(mDecorationContainerSurface)
|
||||||
|
.build();
|
||||||
|
View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
|
||||||
|
|
||||||
|
t.setPosition(
|
||||||
|
windowSurfaceControl, xPos, yPos)
|
||||||
|
.setWindowCrop(windowSurfaceControl, width, height)
|
||||||
|
.show(windowSurfaceControl);
|
||||||
|
final WindowManager.LayoutParams lp =
|
||||||
|
new WindowManager.LayoutParams(width, height,
|
||||||
|
WindowManager.LayoutParams.TYPE_APPLICATION,
|
||||||
|
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
|
||||||
|
lp.setTitle("Additional window of Task=" + mTaskInfo.taskId);
|
||||||
|
lp.setTrustedOverlay();
|
||||||
|
WindowlessWindowManager windowManager = new WindowlessWindowManager(mTaskInfo.configuration,
|
||||||
|
windowSurfaceControl, null /* hostInputToken */);
|
||||||
|
SurfaceControlViewHost viewHost = mSurfaceControlViewHostFactory
|
||||||
|
.create(mDecorWindowContext, mDisplay, windowManager);
|
||||||
|
viewHost.setView(v, lp);
|
||||||
|
return new AdditionalWindow(windowSurfaceControl, viewHost,
|
||||||
|
mSurfaceControlTransactionSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
static class RelayoutParams{
|
static class RelayoutParams{
|
||||||
RunningTaskInfo mRunningTaskInfo;
|
RunningTaskInfo mRunningTaskInfo;
|
||||||
int mLayoutResId;
|
int mLayoutResId;
|
||||||
@@ -395,6 +433,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
int mOutsetLeftId;
|
int mOutsetLeftId;
|
||||||
int mOutsetRightId;
|
int mOutsetRightId;
|
||||||
|
|
||||||
|
int mCaptionX;
|
||||||
|
int mCaptionY;
|
||||||
|
|
||||||
void setOutsets(int leftId, int topId, int rightId, int bottomId) {
|
void setOutsets(int leftId, int topId, int rightId, int bottomId) {
|
||||||
mOutsetLeftId = leftId;
|
mOutsetLeftId = leftId;
|
||||||
mOutsetTopId = topId;
|
mOutsetTopId = topId;
|
||||||
@@ -402,6 +443,11 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
mOutsetBottomId = bottomId;
|
mOutsetBottomId = bottomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCaptionPosition(int left, int top) {
|
||||||
|
mCaptionX = left;
|
||||||
|
mCaptionY = top;
|
||||||
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
mLayoutResId = Resources.ID_NULL;
|
mLayoutResId = Resources.ID_NULL;
|
||||||
mCaptionHeightId = Resources.ID_NULL;
|
mCaptionHeightId = Resources.ID_NULL;
|
||||||
@@ -412,6 +458,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
mOutsetBottomId = Resources.ID_NULL;
|
mOutsetBottomId = Resources.ID_NULL;
|
||||||
mOutsetLeftId = Resources.ID_NULL;
|
mOutsetLeftId = Resources.ID_NULL;
|
||||||
mOutsetRightId = Resources.ID_NULL;
|
mOutsetRightId = Resources.ID_NULL;
|
||||||
|
|
||||||
|
mCaptionX = 0;
|
||||||
|
mCaptionY = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,10 +468,14 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
int mWidth;
|
int mWidth;
|
||||||
int mHeight;
|
int mHeight;
|
||||||
T mRootView;
|
T mRootView;
|
||||||
|
int mDecorContainerOffsetX;
|
||||||
|
int mDecorContainerOffsetY;
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
mWidth = 0;
|
mWidth = 0;
|
||||||
mHeight = 0;
|
mHeight = 0;
|
||||||
|
mDecorContainerOffsetX = 0;
|
||||||
|
mDecorContainerOffsetY = 0;
|
||||||
mRootView = null;
|
mRootView = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,4 +485,41 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
return new SurfaceControlViewHost(c, d, wmm);
|
return new SurfaceControlViewHost(c, d, wmm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass for additional windows associated with this WindowDecoration
|
||||||
|
*/
|
||||||
|
static class AdditionalWindow {
|
||||||
|
SurfaceControl mWindowSurface;
|
||||||
|
SurfaceControlViewHost mWindowViewHost;
|
||||||
|
Supplier<SurfaceControl.Transaction> mTransactionSupplier;
|
||||||
|
|
||||||
|
private AdditionalWindow(SurfaceControl surfaceControl,
|
||||||
|
SurfaceControlViewHost surfaceControlViewHost,
|
||||||
|
Supplier<SurfaceControl.Transaction> transactionSupplier) {
|
||||||
|
mWindowSurface = surfaceControl;
|
||||||
|
mWindowViewHost = surfaceControlViewHost;
|
||||||
|
mTransactionSupplier = transactionSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseView() {
|
||||||
|
WindowlessWindowManager windowManager = mWindowViewHost.getWindowlessWM();
|
||||||
|
|
||||||
|
if (mWindowViewHost != null) {
|
||||||
|
mWindowViewHost.release();
|
||||||
|
mWindowViewHost = null;
|
||||||
|
}
|
||||||
|
windowManager = null;
|
||||||
|
final SurfaceControl.Transaction t = mTransactionSupplier.get();
|
||||||
|
boolean released = false;
|
||||||
|
if (mWindowSurface != null) {
|
||||||
|
t.remove(mWindowSurface);
|
||||||
|
mWindowSurface = null;
|
||||||
|
released = true;
|
||||||
|
}
|
||||||
|
if (released) {
|
||||||
|
t.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify;
|
|||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -64,6 +65,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -102,12 +104,14 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
|
private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
|
||||||
private SurfaceControl.Transaction mMockSurfaceControlStartT;
|
private SurfaceControl.Transaction mMockSurfaceControlStartT;
|
||||||
private SurfaceControl.Transaction mMockSurfaceControlFinishT;
|
private SurfaceControl.Transaction mMockSurfaceControlFinishT;
|
||||||
|
private SurfaceControl.Transaction mMockSurfaceControlAddWindowT;
|
||||||
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
|
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mMockSurfaceControlStartT = createMockSurfaceControlTransaction();
|
mMockSurfaceControlStartT = createMockSurfaceControlTransaction();
|
||||||
mMockSurfaceControlFinishT = createMockSurfaceControlTransaction();
|
mMockSurfaceControlFinishT = createMockSurfaceControlTransaction();
|
||||||
|
mMockSurfaceControlAddWindowT = createMockSurfaceControlTransaction();
|
||||||
|
|
||||||
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
|
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
|
||||||
.create(any(), any(), any());
|
.create(any(), any(), any());
|
||||||
@@ -227,8 +231,8 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
|
|
||||||
verify(captionContainerSurfaceBuilder).setParent(decorContainerSurface);
|
verify(captionContainerSurfaceBuilder).setParent(decorContainerSurface);
|
||||||
verify(captionContainerSurfaceBuilder).setContainerLayer();
|
verify(captionContainerSurfaceBuilder).setContainerLayer();
|
||||||
verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, -46, 8);
|
verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, 20, 40);
|
||||||
verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 300, 64);
|
verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 432, 64);
|
||||||
verify(mMockSurfaceControlStartT).show(captionContainerSurface);
|
verify(mMockSurfaceControlStartT).show(captionContainerSurface);
|
||||||
|
|
||||||
verify(mMockSurfaceControlViewHostFactory).create(any(), eq(defaultDisplay), any());
|
verify(mMockSurfaceControlViewHostFactory).create(any(), eq(defaultDisplay), any());
|
||||||
@@ -242,7 +246,7 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
verify(mMockView).setTaskFocusState(true);
|
verify(mMockView).setTaskFocusState(true);
|
||||||
verify(mMockWindowContainerTransaction)
|
verify(mMockWindowContainerTransaction)
|
||||||
.addRectInsetsProvider(taskInfo.token,
|
.addRectInsetsProvider(taskInfo.token,
|
||||||
new Rect(100, 300, 400, 332),
|
new Rect(100, 300, 400, 364),
|
||||||
new int[] { InsetsState.ITYPE_CAPTION_BAR });
|
new int[] { InsetsState.ITYPE_CAPTION_BAR });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,6 +370,71 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
verify(mMockSurfaceControlViewHost).setView(same(mMockView), any());
|
verify(mMockSurfaceControlViewHost).setView(same(mMockView), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddWindow() {
|
||||||
|
final Display defaultDisplay = mock(Display.class);
|
||||||
|
doReturn(defaultDisplay).when(mMockDisplayController)
|
||||||
|
.getDisplay(Display.DEFAULT_DISPLAY);
|
||||||
|
|
||||||
|
final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
|
||||||
|
final SurfaceControl.Builder decorContainerSurfaceBuilder =
|
||||||
|
createMockSurfaceControlBuilder(decorContainerSurface);
|
||||||
|
mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
|
||||||
|
final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class);
|
||||||
|
final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
|
||||||
|
createMockSurfaceControlBuilder(taskBackgroundSurface);
|
||||||
|
mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
|
||||||
|
final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
|
||||||
|
final SurfaceControl.Builder captionContainerSurfaceBuilder =
|
||||||
|
createMockSurfaceControlBuilder(captionContainerSurface);
|
||||||
|
mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
|
||||||
|
|
||||||
|
final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
|
||||||
|
mMockSurfaceControlTransactions.add(t);
|
||||||
|
final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
|
||||||
|
new ActivityManager.TaskDescription.Builder()
|
||||||
|
.setBackgroundColor(Color.YELLOW);
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
|
||||||
|
.setDisplayId(Display.DEFAULT_DISPLAY)
|
||||||
|
.setTaskDescriptionBuilder(taskDescriptionBuilder)
|
||||||
|
.setBounds(TASK_BOUNDS)
|
||||||
|
.setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
|
||||||
|
.setVisible(true)
|
||||||
|
.build();
|
||||||
|
taskInfo.isFocused = true;
|
||||||
|
taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
|
||||||
|
mRelayoutParams.setOutsets(
|
||||||
|
R.dimen.test_window_decor_left_outset,
|
||||||
|
R.dimen.test_window_decor_top_outset,
|
||||||
|
R.dimen.test_window_decor_right_outset,
|
||||||
|
R.dimen.test_window_decor_bottom_outset);
|
||||||
|
final SurfaceControl taskSurface = mock(SurfaceControl.class);
|
||||||
|
final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
|
||||||
|
windowDecor.relayout(taskInfo);
|
||||||
|
|
||||||
|
final SurfaceControl additionalWindowSurface = mock(SurfaceControl.class);
|
||||||
|
final SurfaceControl.Builder additionalWindowSurfaceBuilder =
|
||||||
|
createMockSurfaceControlBuilder(additionalWindowSurface);
|
||||||
|
mMockSurfaceControlBuilders.add(additionalWindowSurfaceBuilder);
|
||||||
|
|
||||||
|
WindowDecoration.AdditionalWindow additionalWindow = windowDecor.addTestWindow();
|
||||||
|
|
||||||
|
verify(additionalWindowSurfaceBuilder).setContainerLayer();
|
||||||
|
verify(additionalWindowSurfaceBuilder).setParent(decorContainerSurface);
|
||||||
|
verify(additionalWindowSurfaceBuilder).build();
|
||||||
|
verify(mMockSurfaceControlAddWindowT).setPosition(additionalWindowSurface, 20, 40);
|
||||||
|
verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, 432, 64);
|
||||||
|
verify(mMockSurfaceControlAddWindowT).show(additionalWindowSurface);
|
||||||
|
verify(mMockSurfaceControlViewHostFactory, Mockito.times(2))
|
||||||
|
.create(any(), eq(defaultDisplay), any());
|
||||||
|
assertThat(additionalWindow.mWindowViewHost).isNotNull();
|
||||||
|
|
||||||
|
additionalWindow.releaseView();
|
||||||
|
|
||||||
|
assertThat(additionalWindow.mWindowViewHost).isNull();
|
||||||
|
assertThat(additionalWindow.mWindowSurface).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
private TestWindowDecoration createWindowDecoration(
|
private TestWindowDecoration createWindowDecoration(
|
||||||
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
|
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
|
||||||
return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
|
return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
|
||||||
@@ -429,5 +498,20 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
|
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
|
||||||
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
|
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WindowDecoration.AdditionalWindow addTestWindow() {
|
||||||
|
final Resources resources = mDecorWindowContext.getResources();
|
||||||
|
int x = mRelayoutParams.mCaptionX;
|
||||||
|
int y = mRelayoutParams.mCaptionY;
|
||||||
|
int width = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionWidthId);
|
||||||
|
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
|
||||||
|
String name = "Test Window";
|
||||||
|
WindowDecoration.AdditionalWindow additionalWindow =
|
||||||
|
addWindow(R.layout.caption_handle_menu, name, mMockSurfaceControlAddWindowT,
|
||||||
|
x - mRelayoutResult.mDecorContainerOffsetX,
|
||||||
|
y - mRelayoutResult.mDecorContainerOffsetY,
|
||||||
|
width, height);
|
||||||
|
return additionalWindow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user