Skip to content

Commit

Permalink
Merge branch 'LawnchairLauncher:15-dev' into trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
Goooler authored Nov 18, 2024
2 parents 2979727 + 630d885 commit 8a016c5
Show file tree
Hide file tree
Showing 43 changed files with 615 additions and 208 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ plugins {
id 'org.jetbrains.kotlin.plugin.compose' version "2.0.21"
id 'org.jetbrains.kotlin.plugin.parcelize' version "2.0.21"
id 'org.jetbrains.kotlin.plugin.serialization' version "2.0.21"
id "com.google.devtools.ksp" version "2.0.21-1.0.27"
id "com.google.devtools.ksp" version "2.0.21-1.0.28"
id 'com.google.protobuf' version "0.9.4"
id 'app.cash.licensee' version "1.12.0"
id 'dev.rikka.tools.refine' version "4.4.0"
Expand Down
50 changes: 50 additions & 0 deletions lawnchair/res/layout-v28/task_desktop.xml
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.
2 changes: 1 addition & 1 deletion lawnchair/res/values-hu-rHU/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
<!-- Experimental features -->
<string name="font_picker_label">A Betűkészlet testreszabása</string>
<string name="font_picker_description">Egyes szövegek változatlanok maradnak</string>
<string name="smartspace_calendar_label">Az Áttekintés naptárának testreszabása</string>
<string name="smartspace_calendar_label">A \'Bepillantás\' naptárának testreszabása</string>
<string name="smartspace_calendar_description">Lehetővé teszi, hogy a dátum nem gregorián naptárban is megjelenjen</string>
<string name="workspace_increase_max_grid_size_label">A maximális rácsméret-korlát növelése</string>
<string name="workspace_increase_max_grid_size_description">A kezdőképernyő legnagyobb rácsméretének 10×10-ről 20×20-ra való növelése</string>
Expand Down
4 changes: 2 additions & 2 deletions lawnchair/res/values-in-rID/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
<!-- Miscellaneous -->
<string name="what_to_show">Yang ditampilkan</string>
<!-- A11y description -->
<string name="accessibility_service_description">To lock your phone when performing a gesture, and to open Recents via gesture, Lawnchair requires accessibility access.\n\nLawnchair doesn\'t watch any user action, though the privilege to do so is required for all accessibility services. Lawnchair discards any event sent by the system.\n\nIn order to lock your phone, or to open Recents, Lawnchair uses the performGlobalAction Accessibility service.</string>
<string name="accessibility_service_description">Untuk mengunci layar dan membuka aplikasi Terbaru dengan gerakan, Lawnchair perlu izin aksesibilitas.\n\nLawnchair tidak melacak apa yang Anda lakukan di ponsel. Izin ini hanya digunakan untuk mengaktifkan gerakan-gerakan tersebut.\n\nLawnchair menggunakan fitur aksesibilitas performGlobalAction untuk mengunci layar atau membuka aplikasi Terbaru.</string>
<string name="x_by_y">%1$d × %2$d</string>
<string name="x_and_y">%1$s &amp; %2$s</string>
<!--
Expand Down Expand Up @@ -351,7 +351,7 @@
<string name="dt2s_admin_hint">Untuk menggunakan Ketuk Dua Kali untuk Tidur, atur Lawnchair sebagai apli admin perangkat. Ketuk \"Buka pengaturan\", lalu ketuk \"Aktifkan apli admin perangkat ini.\"</string>
<string name="dt2s_admin_warning">Tap Dua Kali untuk Tidur akan dimatikan.</string>
<string name="d2ts_recents_a11y_hint_title">Aktifkan layanan aksesibilitas</string>
<string name="dt2s_a11y_hint">To use Double-Tap to Sleep, turn on the Lawnchair accessibility service. Tap \"Open settings\", select \"Lawnchair\" and turn on \"Use Lawnchair.\"\n\nLawnchair uses Accessibility\'s `performGlobalAction` method to perform this action. This is a sensitive permission that allows monitoring other apps. However, Lawnchair is not configured for that functionality and receives no events.</string>
<string name="dt2s_a11y_hint">Untuk menggunakan Ketuk-Ganda untuk Tidur, aktifkan layanan aksesibilitas Lawnchair. Ketuk \"Buka pengaturan\", pilih \"Lawnchair\" dan aktifkan \"Gunakan Lawnchair\".\n\nLawnchair menggunakan metode performGlobalAction dari Aksesibilitas untuk melakukan tindakan ini. Ini adalah izin sensitif yang memungkinkan pemantauan aplikasi lain. Namun, Lawnchair tidak dikonfigurasi untuk fungsi tersebut dan tidak menerima acara apa pun.</string>
<string name="dt2s_recents_warning_open_settings">Buka pengaturan</string>
<string name="recents_a11y_hint">To use Open Recents, turn on the Lawnchair accessibility service. Tap \"Open settings\", select \"Lawnchair\" and turn on \"Use Lawnchair.\"\n\nLawnchair uses Accessibility\'s `performGlobalAction` method to perform this action. This is a sensitive permission that allows monitoring other apps. However, Lawnchair is not configured for that functionality and receives no events.</string>
<!--
Expand Down
4 changes: 2 additions & 2 deletions lawnchair/res/values-ja-rJP/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@
<string name="event_provider_missing_notification_dots">To use <xliff:g example="My Provider" id="providerName">%1$s</xliff:g>, turn on Notification Dots.</string>
<!-- Toggle button for enabling Smartspace -->
<string name="smartspace_widget_toggle_label">ホーム画面に表示します</string>
<string name="smartspace_widget_toggle_description">At a Glance can be manually added to the home screen by placing the Lawnchair widget</string>
<string name="smartspace_widget_toggle_description">スナップショットは、Lawnchairウィジェットを配置することでホーム画面に手動で追加できます</string>
<!-- List of available providers -->
<string name="smartspace_mode_label">At a Glance のプロバイダー</string>
<string name="smartspace_mode_google">Google</string>
Expand Down Expand Up @@ -376,7 +376,7 @@
<!-- General and home screen settings -->
<string name="home_screen_rotation_label">ホーム画面の回転</string>
<string name="home_screen_rotation_description">デバイスが回転した際にホーム画面も回転します</string>
<string name="wallpaper_blur">Blur wallpaper (experimental)</string>
<string name="wallpaper_blur">ぼやけた壁紙(実験的な機能)</string>
<string name="wallpaper_background_blur">Blur intensity</string>
<string name="wallpaper_background_blur_factor">Factor threshold</string>
<string name="auto_add_shortcuts_label">Add new apps to home screen</string>
Expand Down
2 changes: 1 addition & 1 deletion lawnchair/res/values-tr-rTR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
Notifications
-->
<string name="set_default_launcher_tip">Kısayollar ve ek özellikler için Lawnchair\'ı varsayılan olarak başlatmayı yapın</string>
<string name="set_default_launcher_tip">Kısayollar ve ek özellikler için Lawnchair\'ı varsayılan başlatıcınız yapın</string>
<string name="notification_dots">Bildirim rozetleri</string>
<string name="show_notification_count">Bildirim sayımı göster</string>
<string name="notification_dots_color">Bildirim noktası rengi</string>
Expand Down
2 changes: 1 addition & 1 deletion lawnchair/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<string name="managed_by_lawnchair">由 Lawnchair 管理</string>
<!-- When mentioning settings UI -->
<string name="smartspace_preferences">首选项</string>
<string name="settings_button_text">主页设置</string>
<string name="settings_button_text">启动器设置</string>
<string name="system_settings">系统设置</string>
<string name="title_change_settings">更改设置</string>
<!--
Expand Down
211 changes: 187 additions & 24 deletions lawnchair/src/app/lawnchair/util/LawnchairWindowManagerProxy.kt
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()
}
}
Loading

0 comments on commit 8a016c5

Please sign in to comment.