forked from LawnchairLauncher/lawnchair
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'LawnchairLauncher:15-dev' into trunk
- Loading branch information
Showing
43 changed files
with
615 additions
and
208 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?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.quickstep.views.DesktopTaskView | ||
xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
android:clipChildren="true" | ||
android:defaultFocusHighlightEnabled="false" | ||
android:focusable="true"> | ||
|
||
<View | ||
android:id="@+id/background" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" /> | ||
|
||
<!-- | ||
TODO(b249371338): DesktopTaskView extends from TaskView. TaskView expects TaskThumbnailView | ||
and IconView with these ids to be present. Need to refactor RecentsView to accept child | ||
views that do not inherint from TaskView only or create a generic TaskView that have | ||
N number of tasks. | ||
--> | ||
<com.android.quickstep.views.TaskThumbnailViewDeprecated | ||
android:id="@+id/snapshot" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:visibility="gone" /> | ||
|
||
<com.android.quickstep.views.IconView | ||
android:id="@+id/icon" | ||
android:layout_width="@dimen/task_thumbnail_icon_size" | ||
android:layout_height="@dimen/task_thumbnail_icon_size" | ||
android:focusable="false" | ||
android:importantForAccessibility="no" /> | ||
|
||
</com.android.quickstep.views.DesktopTaskView> |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
211 changes: 187 additions & 24 deletions
211
lawnchair/src/app/lawnchair/util/LawnchairWindowManagerProxy.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,208 @@ | ||
package app.lawnchair.util | ||
|
||
import android.content.Context | ||
import android.content.res.Resources | ||
import android.graphics.Insets | ||
import android.graphics.Rect | ||
import android.hardware.display.DisplayManager | ||
import android.util.ArrayMap | ||
import android.view.Display | ||
import android.view.Display.DEFAULT_DISPLAY | ||
import android.view.DisplayCutout | ||
import android.view.Surface | ||
import android.view.WindowInsets | ||
import android.view.WindowManager | ||
import androidx.annotation.Keep | ||
import app.lawnchair.LawnchairApp | ||
import androidx.annotation.VisibleForTesting | ||
import com.android.launcher3.Utilities | ||
import com.android.launcher3.testing.shared.ResourceUtils | ||
import com.android.launcher3.util.RotationUtils.deltaRotation | ||
import com.android.launcher3.util.RotationUtils.rotateRect | ||
import com.android.launcher3.util.WindowBounds | ||
import com.android.launcher3.util.window.CachedDisplayInfo | ||
import com.android.launcher3.util.window.WindowManagerProxy | ||
import kotlin.math.max | ||
|
||
@Keep | ||
class LawnchairWindowManagerProxy(context: Context) : WindowManagerProxy(Utilities.ATLEAST_T) { | ||
|
||
override fun getRotation(displayInfoContext: Context): Int { | ||
// if (LawnchairApp.isAtleastT) { | ||
// return displayInfoContext.resources.configuration.windowConfiguration.rotation | ||
// } | ||
return super.getRotation(displayInfoContext) | ||
override fun estimateInternalDisplayBounds(displayInfoContext: Context): ArrayMap<CachedDisplayInfo, List<WindowBounds>> { | ||
val info = getDisplayInfo(displayInfoContext).normalize(this) | ||
val bounds = estimateWindowBounds(displayInfoContext, info) | ||
return ArrayMap<CachedDisplayInfo, List<WindowBounds>>().apply { put(info, bounds) } | ||
} | ||
|
||
override fun getRealBounds(displayInfoContext: Context, info: CachedDisplayInfo): WindowBounds { | ||
val windowMetrics = if (Utilities.ATLEAST_R) { | ||
displayInfoContext.getSystemService(WindowManager::class.java)?.maximumWindowMetrics | ||
} else { | ||
null | ||
} | ||
return if (windowMetrics != null) { | ||
val insets = Rect() | ||
normalizeWindowInsets(displayInfoContext, windowMetrics.windowInsets, insets) | ||
WindowBounds(windowMetrics.bounds, insets, info.rotation) | ||
} else { | ||
WindowBounds(Rect(), Rect(), info.rotation) | ||
} | ||
} | ||
|
||
override fun normalizeWindowInsets(context: Context, oldInsets: WindowInsets, outInsets: Rect): WindowInsets { | ||
if (!Utilities.ATLEAST_R || !mTaskbarDrawnInProcess) { | ||
outInsets.set( | ||
oldInsets.systemWindowInsetLeft, | ||
oldInsets.systemWindowInsetTop, | ||
oldInsets.systemWindowInsetRight, | ||
oldInsets.systemWindowInsetBottom, | ||
) | ||
return oldInsets | ||
} | ||
|
||
val insetsBuilder = WindowInsets.Builder(oldInsets) | ||
val navInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars()) | ||
|
||
val systemRes = context.resources | ||
val config = systemRes.configuration | ||
|
||
val isLargeScreen = config.smallestScreenWidthDp > MIN_TABLET_WIDTH | ||
val isGesture = isGestureNav(context) | ||
val isPortrait = config.screenHeightDp > config.screenWidthDp | ||
|
||
val bottomNav = if (isLargeScreen) { | ||
0 | ||
} else if (isPortrait) { | ||
getDimenByName(systemRes, ResourceUtils.NAVBAR_HEIGHT) | ||
} else if (isGesture) { | ||
getDimenByName(systemRes, ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE) | ||
} else { | ||
0 | ||
} | ||
var leftNav = navInsets.left | ||
var rightNav = navInsets.right | ||
if (!isLargeScreen && !isGesture && !isPortrait) { | ||
val navBarWidth = getDimenByName(systemRes, ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE) | ||
when (getRotation(context)) { | ||
Surface.ROTATION_90 -> rightNav = navBarWidth | ||
Surface.ROTATION_270 -> leftNav = navBarWidth | ||
} | ||
} | ||
val newNavInsets = Insets.of(leftNav, navInsets.top, rightNav, bottomNav) | ||
insetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets) | ||
insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets) | ||
|
||
val statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars()) | ||
val newStatusBarInsets = Insets.of( | ||
statusBarInsets.left, | ||
getStatusBarHeight(context, isPortrait, statusBarInsets.top), | ||
statusBarInsets.right, | ||
statusBarInsets.bottom, | ||
) | ||
insetsBuilder.setInsets(WindowInsets.Type.statusBars(), newStatusBarInsets) | ||
insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.statusBars(), newStatusBarInsets) | ||
|
||
if (isGesture) { | ||
val oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement()) | ||
val newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top, oldTappableInsets.right, 0) | ||
insetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets) | ||
} | ||
|
||
applyDisplayCutoutBottomInsetOverrideOnLargeScreen( | ||
context, | ||
isLargeScreen, | ||
Utilities.dpToPx( | ||
config.screenWidthDp.toFloat(), | ||
), | ||
oldInsets, | ||
insetsBuilder, | ||
) | ||
|
||
val result = insetsBuilder.build() | ||
val systemWindowInsets = result.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout()) | ||
outInsets.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right, systemWindowInsets.bottom) | ||
return result | ||
} | ||
|
||
override fun rotateCutout( | ||
original: DisplayCutout, | ||
startWidth: Int, | ||
startHeight: Int, | ||
fromRotation: Int, | ||
toRotation: Int, | ||
): DisplayCutout? { | ||
val safeCutout = getSafeInsets(original) | ||
rotateRect(safeCutout, deltaRotation(fromRotation, toRotation)) | ||
|
||
return if (Utilities.ATLEAST_Q) { | ||
DisplayCutout(Insets.of(safeCutout), null, null, null, null) | ||
} else { | ||
null | ||
} | ||
} | ||
|
||
override fun applyDisplayCutoutBottomInsetOverrideOnLargeScreen( | ||
context: Context, | ||
isLargeScreen: Boolean, | ||
screenWidthPx: Int, | ||
windowInsets: WindowInsets, | ||
insetsBuilder: WindowInsets.Builder, | ||
) { | ||
if (!isLargeScreen || !Utilities.ATLEAST_S) return | ||
|
||
val displayCutout = windowInsets.displayCutout ?: return | ||
if (!areBottomDisplayCutoutsSmallAndAtCorners(displayCutout.boundingRectBottom, screenWidthPx, context.resources)) return | ||
|
||
val oldDisplayCutoutInset = windowInsets.getInsets(WindowInsets.Type.displayCutout()) | ||
val newDisplayCutoutInset = Insets.of(oldDisplayCutoutInset.left, oldDisplayCutoutInset.top, oldDisplayCutoutInset.right, 0) | ||
insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.displayCutout(), newDisplayCutoutInset) | ||
} | ||
|
||
@VisibleForTesting | ||
fun areBottomDisplayCutoutsSmallAndAtCorners( | ||
cutoutRectBottom: Rect, | ||
screenWidthPx: Int, | ||
resources: Resources, | ||
): Boolean { | ||
if (cutoutRectBottom.isEmpty) return false | ||
val maxCutoutSizePx = dpToPx(resources, 32) | ||
return cutoutRectBottom.right <= maxCutoutSizePx || cutoutRectBottom.left >= (screenWidthPx - maxCutoutSizePx) | ||
} | ||
|
||
override fun getStatusBarHeight(context: Context, isPortrait: Boolean, statusBarInset: Int): Int { | ||
// if (LawnchairApp.isAtleastT) { | ||
// return SystemBarUtils.getStatusBarHeight(context) | ||
// } | ||
return super.getStatusBarHeight(context, isPortrait, statusBarInset) | ||
val systemRes = context.resources | ||
val statusBarHeight = getDimenByName(systemRes, if (isPortrait) ResourceUtils.STATUS_BAR_HEIGHT_PORTRAIT else ResourceUtils.STATUS_BAR_HEIGHT_LANDSCAPE, ResourceUtils.STATUS_BAR_HEIGHT) | ||
return max(statusBarInset, statusBarHeight) | ||
} | ||
|
||
override fun estimateInternalDisplayBounds(displayInfoContext: Context): ArrayMap<CachedDisplayInfo, List<WindowBounds>> { | ||
if (LawnchairApp.isAtleastT) { | ||
val result = ArrayMap<CachedDisplayInfo, List<WindowBounds>>() | ||
val windowManager = displayInfoContext.getSystemService(WindowManager::class.java) | ||
// val possibleMaximumWindowMetrics = | ||
// windowManager!!.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY) | ||
// for (windowMetrics in possibleMaximumWindowMetrics) { | ||
// val info = getDisplayInfo(windowMetrics, Surface.ROTATION_0) | ||
// val bounds = estimateWindowBounds(displayInfoContext, info) | ||
// result[info] = bounds | ||
// } | ||
return result | ||
} | ||
return super.estimateInternalDisplayBounds(displayInfoContext) | ||
private fun getDimenByName(resources: Resources, vararg dimenNames: String): Int { | ||
for (name in dimenNames) { | ||
val resId = resources.getIdentifier(name, "dimen", "android") | ||
if (resId > 0) return resources.getDimensionPixelSize(resId) | ||
} | ||
return 0 | ||
} | ||
|
||
override fun getDisplay(displayInfoContext: Context): Display? { | ||
return try { | ||
if (Utilities.ATLEAST_R) { | ||
displayInfoContext.display | ||
} else { | ||
displayInfoContext.getSystemService(DisplayManager::class.java)?.getDisplay( | ||
DEFAULT_DISPLAY, | ||
) | ||
} | ||
} catch (e: UnsupportedOperationException) { | ||
displayInfoContext.getSystemService(DisplayManager::class.java)?.getDisplay( | ||
DEFAULT_DISPLAY, | ||
) | ||
} | ||
} | ||
|
||
override fun getRotation(context: Context): Int { | ||
val display = context.getSystemService(WindowManager::class.java)?.defaultDisplay | ||
return display?.rotation ?: Surface.ROTATION_0 | ||
} | ||
|
||
private fun dpToPx(resources: Resources, dp: Int): Int { | ||
return (dp * resources.displayMetrics.density).toInt() | ||
} | ||
} |
Oops, something went wrong.