87844 Commits
Author SHA1 Message Date
TMCandClaude Fable 5.2 cdb076bba5 Add the alphabet side setting, screen-reader support and a trimmed drawer settings screen
PRD AD-15 and SI-10, plus polish found while checking the M4 rows on the emulator.

Wave alphabet
- New setting "Alphabet on the left edge" for left-handed use. Rows keep clear of the
  alphabet on whichever edge it sits; a scrub from the left darkens the list under the
  wave, because there the letters cross the icons and names.
- Screen readers see the strip as one slider: it reads the letter the list is at, and the
  adjust gesture moves one letter at a time.
- Letters shrink to fit their slot when a large system font would make them overlap.

Settings
- FlexeraDrawerSettings replaces Lawnchair's App drawer screen, whose grid options
  (columns, row height, icon and label size, drawer folders, scroll bar, panel colour and
  opacity) do nothing in the list drawer or break its white-on-transparent look.
- Settings home and search hint no longer mention column counts or web results.

Search
- The search field keeps its pill while typing; without a drawer panel behind it, the
  dark text sat directly on the wallpaper.

Checked on the Android 17 emulator: drawer search, hiding and restoring an app,
notification dots, swipe down for notifications, the left-edge alphabet and its scrub,
and the slider node in the accessibility tree.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
v0.1.0
2026-11-11 22:44:43 +01:00
TMCandClaude Fable 5.2 1e49441967 Add self-update from a public release repository
The app is distributed privately, outside any store. Every version is published as a
release with the APK attached in https://git.mariosem.es/msemes/Flexera-Launcher-Releases,
and installed copies update themselves from there.

Versioning
- flexera/version.properties holds the version name (now 0.1.0); build.gradle derives the
  version code from it. This replaces Lawnchair's 16_00_02_01_00 / "16.Dev.(hash)".
- Debug builds always use the debug key, so the release key signs releases only.

Updater (app.flexera.update.FlexeraUpdater)
- Asks the release repository for the latest release at most once a day, when the home
  screen or settings come to the front, and on demand from Settings > About > Updates.
- Downloads the APK into the cache, checks that it is a newer build of this app, and
  hands it to Android's installer. Android enforces the signature.
- Posts a notification when an automatic check finds a newer version.
- Off in debug builds, whose app ID differs from the released one.

Network policy (reverses PRD SI-5, at the owner's request for in-app updates)
- The INTERNET permission is back, plus REQUEST_INSTALL_PACKAGES.
- The update check is the only network use. Lawnchair's online features stay off through
  FlexeraNetwork.onlineFeaturesAllowed: web suggestions, the announcement feed, and the
  crash-report upload button.
- The About screen's privacy text says what the app now does online.

Releasing
- flexera/release.ps1 raises the version, builds the signed APK, checks its signature,
  creates the release and uploads the APK.

Also carries the strings for the next commit (alphabet side and drawer settings).

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 22:44:42 +01:00
TMCandClaude Fable 5.2 9f66d06f4d Add the wave alphabet, swipe up and hold, and the transparent fading drawer
PRD M3 (AD-4 to AD-6, AD-17), plus three look changes the owner asked for.

Wave alphabet
- WaveAlphabetView (flexera/src): a strip of letters on the drawer's end edge showing only
  letters that have apps. Touching it jumps the list to that letter with a haptic tick; the
  letters near the finger bulge away from the edge and reach further the further in the
  finger moves; the selected letter is enlarged.
- The strip reserves the edge from the system back gesture and tells the drawer not to
  drag closed under a scrub.
- Launcher3's scroll bar is hidden by default and no longer takes touches while hidden.

Swipe up and hold
- NoButtonNavbarToOverviewTouchController reuses its motion-pause detector on an ordinary
  swipe up from the home screen: a pause finishes opening the drawer and hands the same
  touch to the alphabet. Swipes that start on the navigation bar keep their stock meaning.

Look
- The drawer fades in over the home screen instead of sliding up from the bottom.
- No background panel or drag handle (drawer opacity default 0); the wallpaper keeps
  Lawnchair's blur and scrim.
- App names, letter headers and alphabet letters are white with a soft shadow.

Tested on the Android 17 emulator: quick swipe opens the drawer, edge scrub jumps the
list, swipe up and hold opens the drawer and scrubs from mid-screen, Back closes it.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 22:12:40 +01:00
TMCandClaude Fable 5.2 76c3603693 Turn the app drawer into a one-column list with letter headers
PRD M2 (AD-1 to AD-3, AD-7, AD-8, HS-7). The drawer keeps Launcher3's adapter, sorting,
live updates, click, long-press menu and drag; only what differs from the grid is new.

- FlexeraDrawer (flexera/src): column count, row styling, and a letter-header adapter item
- flexera/res/layout/all_apps_icon.xml overrides Launcher3's grid cell with a horizontal
  row (46dp icon, name beside it, 64dp tall)
- AlphabeticalAppsList adds a header item at the start of each letter group and points
  the fast-scroll section at it; Private Space keeps its own framing
- BaseAllAppsAdapter creates and binds the header view type and styles rows
- DeviceProfileOverrides forces one drawer column
- DeviceProfile.getAllAppsIconStartMargin returns the row padding for a one-column
  drawer, which keeps the search bar full width
- Suggested apps row above the list is off by default

Tested on the Android 17 emulator: scrolling, tap to launch, long-press menu, drag to the
home screen, and live removal and return of an app all work. The right-edge fast
scroller did not respond to scripted drags and still needs a hand test.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 21:25:41 +01:00
TMCandClaude Fable 5.2 9376781e8a Replace Lawnchair's About screen with Flexera Launcher's own
Lawnchair's screen showed its logo, team and community links and loaded contributor
data from the network. FlexeraAbout (flexera/src) shows the app's own icon, name and
version, credits Lawnchair as the project it is built on, states the privacy position,
and keeps the open-source licence list. It makes no network requests.

The About route in PreferenceNavigation now points at it; Lawnchair's About.kt is untouched.

Tested on the Android 17 emulator: the screen renders, the licence list opens, and
no network request or guard message is logged.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 20:59:06 +01:00
TMCandClaude Fable 5.2 25df1a89e6 Remove the INTERNET permission and guard the network call sites
PRD SI-5: nothing leaves the device.

- flexera/AndroidManifest.xml removes android.permission.INTERNET; it is attached to the
  debug and release build types so it outranks flavor and library manifests
- FlexeraNetwork (new, flexera/src): isAvailable() plus a crash guard, because OkHttp
  rethrows Android's SecurityException on its dispatcher thread and that killed the launcher
- Drawer search skips web suggestions when the permission is missing
- LawnchairApp installs the guard; the bug reporter ignores the same exception

Tested on the Android 17 emulator: typing in the drawer search and opening the About
screen no longer crash; the guard logged and absorbed six refused requests.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 20:48:43 +01:00
TMCandClaude Fable 5.2 feb18adacc Rebrand Lawnchair fork as Flexera Launcher
- App ID com.sema.flexeralauncher (debug builds add .debug)
- App name Flexera Launcher and an adaptive icon built from the artwork in flexera/branding
- New overlay folder flexera/res, wired into the lawnWithQuickstepGithub source set,
  so branding and defaults override Lawnchair's without editing its files
- Defaults switched off: At a Glance, Lawnchair's announcement feed, nightly updater
- English strings that named Lawnchair now say Flexera Launcher

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 20:31:34 +01:00
caizhixingandcaizhixing f4b71266fa fix: crash when starting home with fade-out remote transition on Android 14+ (#7528)
Co-authored-by: caizhixing <caizhixing@users.noreply.github.com>
2026-11-11 18:38:26 +08:00
caizhixingandcaizhixing 6c592e7924 fix: restart non-default-home Lawnchair with a home-category intent (#7525)
restartLauncher()'s fallback for when Lawnchair isn't the current default home restarts it via PackageManager.getLaunchIntentForPackage(), which builds a CATEGORY_LAUNCHER (standard-typed) intent to the home activity. Some Android 8-10 OEM ROMs react to that launch by trying to re-type the home task and killing the app with RemoteServiceException("Can't change activity type once set: ... activityType=standard") delivered via SCHEDULE_CRASH, which cannot be caught at runtime. Launch the same activity with a home-category intent pinned to our own package instead; the resolved target and flags are unchanged (NEW_TASK was implicit in the launch intent, CLEAR_TOP stays).

Co-authored-by: caizhixing <caizhixing@users.noreply.github.com>
2026-11-11 15:02:37 +08:00
caizhixingandcaizhixing c1d296813e fix: NPE in Workspace.onDropExternal when the dropped view fails to attach to the workspace (#7524)
Co-authored-by: caizhixing <caizhixing@users.noreply.github.com>
2026-11-11 14:58:30 +08:00
renovate[bot] 5018e8db08 chore(deps): update gradle to v9.9.1 (#7518)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-10 18:27:29 +00:00
B Vishal ChandrakanthandCopilot ce82ac1248 feat: add tilt to swipe pages for home screen rearrangement and fix app drawer gap (#7500)
* feat and fix : Add Tilt to swipe pages setting

Replace the multi-level Motion controls with a single Home screen toggle named “Tilt to swipe pages,” positioned below Infinite scrolling. Update the description to explain that tilting the phone moves between pages while rearranging apps or widgets, and make the pan controller use the toggle directly while retaining the existing preference key for compatibility. Fix for "[BUG] Large empty gap between app drawer search bar and app grid when app suggestions are disabled
 #7490"

* EDITS : Coderabbit suggested edits for PR #7500

* Coderabbit suggested changes (2) #7500

* Update gradle-daemon-jvm.properties

* Remove unrelated Gradle toolchain changes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add docstrings for pan-to-move and all apps header changes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add a tilt sensitivity control

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-09 20:59:50 +08:00
caizhixingandcaizhixing d180feb55f fix: crash when the icon surface view still has a parent on resume (#7513)
LawnchairFloatingSurfaceView.removeViewImmediate() skipped the removal when
isAttachedToWindow was false. onNewIntent is delivered inside
performResumeActivity, while the window can still be re-attaching: the view is
already a child of the drag layer but not attached yet. The removal was
skipped, so the following show() crashed on addView() with

  IllegalStateException: The specified child already has a parent.
  You must call removeView() on the child's parent first.

FloatingSurfaceView removes the view unconditionally, and removeViewInLayout()
is a no-op when the view has no parent, so match it.

Co-authored-by: caizhixing <caizhixing@users.noreply.github.com>
2026-11-09 20:49:49 +08:00
caizhixingandcaizhixing 34d1c3ef88 fix: drop the stale two-pane paged widget sheet overlay (#7514)
lawnchair/res/layout/widgets_two_pane_sheet_paged_view.xml is a leftover copy
of the 2021 two-pane layout that shadows the current one in res/. It is
inflated by WidgetsTwoPaneSheet when a work profile is present, but the AOSP
code has moved on:

- WidgetsFullSheet.setupViews() looks up R.id.search_widgets_list_view, which
  only exists in the current layout. The old copy has no search results list,
  so the lookup returns null and AdapterHolder.setup() crashes on
  setOutlineProvider() while the sheet is being inflated.
- It is also missing R.id.suggestions_header and repeats the "Widgets" title
  that the outer widgets_two_pane_sheet.xml already provides.

Deleting the overlay lets the AOSP layout in res/ win, matching the
recyclerview variant which was already realigned with AOSP in #7188.

Co-authored-by: caizhixing <caizhixing@users.noreply.github.com>
2026-11-09 16:59:11 +07:00
caizhixingandcaizhixing 0614d0b48a fix : NPE in Workspace.onDrop when the dropped cell is detached from the workspace (#7457)
Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-11-09 16:58:58 +07:00
x-JOCandClaude Opus 5.5 5152a54bc0 perf(startup): install the bundled baseline profile on sideloaded builds (#7412)
* fix(startup): install the shipped baseline profile on sideloaded builds

Removing androidx.startup's InitializationProvider (AOSP b/197780098)
also removed ProfileInstallerInitializer, so GitHub and Nightly APKs
never wrote the bundled baseline profile and ran unoptimised until
background dexopt built a profile of its own.

Do the initializer's job from LawnchairApp instead: main process only,
5 s after start, on the background-priority ordered executor. The
provider stays removed, so no other library initializes eagerly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(startup): only install the profile from the main process on API 26-27

Below API 28 the version check let every process through, including
:bugReport. Look up this pid's process name with ActivityManager there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:12:50 +07:00
Lawnchair BotandCrowdin Bot 677e9c4aa3 New Crowdin translations by GitHub Action (#7507)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-11-08 00:21:47 +00:00
SEED264andClaude Opus 5.5 aeb92c164b fix(bugreport): prevent the launcher from hanging after a crash (#7499)
The bug report file name used the locale-dependent
SimpleDateFormat.getDateTimeInstance(), which yields '/' in some
locales (e.g. ja_JP: "2026/09/28 12:34:56"). The resulting path had
non-existent parent directories, so createNewFile() threw inside the
uncaught exception handler and the default handler was never invoked,
leaving the process frozen instead of restarting.

- Use a fixed, locale-independent format (yyyy-MM-dd_HH-mm-ss, Locale.US)
- Always delegate to the default handler via try/finally so the process
  is killed even if generating the report fails

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-08 00:29:32 +08:00
renovate[bot] 94b36676fd chore(deps): update gradle to v9.9.0 (#7503)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-06 18:50:43 +00:00
caizhixingandcaizhixing bf784dc6fb fix: survive a missing restriction bypass native library (#7484)
* fix: don't crash at startup when the restriction bypass lib is missing

Unseal.unseal() loads ChickenHook's libnrb.so. Repackaged APKs and
multi-open containers can fail to load it, in which case the call throws
UnsatisfiedLinkError (an Error) that catch (Exception) does not handle. This
runs from Application.onCreate(), so the process crash-loops forever.

Catch Exception | LinkageError. A failed unseal only disables the hidden API
exemption for that launch; other Errors (OOM, etc.) still propagate.

* fix: don't crash reading allowEnterPip when the restriction bypass is broken

getAllowEnterPip() uses RestrictionBypass below SDK 35. If the native bypass
library failed to load, the bypass class is permanently broken and any further
access throws LinkageError (ExceptionInInitializerError on the first touch,
NoClassDefFoundError afterwards), which catch (ReflectiveOperationException)
does not handle.

Return false (PIP not allowed) instead of crashing the transition.

---------

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-11-06 15:19:43 +08:00
caizhixingandcaizhixing 2b719d5134 fix(notification): NPE when the listener disconnects before connecting (#7483)
mSettingsCache is only assigned in onListenerConnected(), but
onListenerDisconnected() unregisters from it unconditionally. The framework
calls onListenerDisconnected() from NotificationListenerService.onDestroy(),
so a service that is destroyed before it ever connects dereferences null and
kills the process.

Guard the unregister; the connected path is unchanged.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-11-06 14:11:10 +08:00
caizhixingandcaizhixing fcbf433f39 fix(folder): crash when opening a folder with an empty preview (#7482)
getAnimationData() read itemsInPreview[0] to derive the base icon size. The
preview list can be empty when the folder has no bound child views yet, which
made opening the folder crash with an IndexOutOfBoundsException.

Fall back to the device profile icon size when the list is empty; the normal
path is unchanged.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-11-06 14:05:10 +08:00
renovate[bot] 448f542eac chore(deps): update agp to v9.5.1 (#7498)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-05 23:50:09 +00:00
Pun Butrach b66d36f8cf fix: HW bitmaps copied to SW before placed inside adaptive icons (#7496) 2026-11-05 15:49:42 +00:00
8801864504 fix: crash in icon cache when a component disappears during package update (#7481)
On Android 11 and below, LawnchairActivityCachingLogic#loadIcon resolves
ActivityInfo through PackageManager#getActivityInfo because
LauncherActivityInfo#getActivityInfo is only public since Android 12. When a
package is updated while the launcher refreshes its icon cache, one of its
launcher activities can vanish between LauncherApps handing out the activity
list and this lookup. The resulting NameNotFoundException is uncaught and
kills the model thread:

Fatal Exception: android.content.pm.PackageManager$NameNotFoundException
       at android.app.ApplicationPackageManager.getActivityInfo(ApplicationPackageManager.java:471)
       at app.lawnchair.LawnchairActivityCachingLogic.loadIcon(LawnchairActivityCachingLogic.kt:60)
       at com.android.launcher3.icons.cache.BaseIconCache.addIconToDBAndMemCache(BaseIconCache.kt:235)
       at com.android.launcher3.icons.IconCache.updateIconsForPkg(IconCache.java:206)
       at com.android.launcher3.model.PackageUpdatedTask.execute(PackageUpdatedTask.java:160)
       at com.android.launcher3.LauncherModel.enqueueModelUpdateTask(LauncherModel.kt:412)

Catch the exception and return BaseIconCache#getDefaultIcon instead:
addIconToDBAndMemCache already treats the default icon as "could not be
loaded" and skips the DB/memory cache entry, matching how other icon load
failures are handled. The two other PackageManager#getActivityInfo call
sites (ThemedIconCompat, SearchResultIcon) already catch this exception; the
CachingLogic was the only unguarded one.

Android 12+ is unaffected: it reads the ActivityInfo snapshot from
LauncherActivityInfo directly.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
Co-authored-by: Pun Butrach <pun.butrach@gmail.com>
2026-11-05 15:20:18 +00:00
Pun Butrach f1c1220f1f Revert "chore(deps): update plugin google-protobuf to v0.10.1" (#7494)
This reverts commit 428b6a6062.
2026-11-05 14:10:29 +00:00
renovate[bot] 428b6a6062 chore(deps): update plugin google-protobuf to v0.10.1 (#7493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-04 22:47:22 +00:00
renovate[bot] ee30d67758 fix(deps): update dependency androidx.test.uiautomator:uiautomator to v2.4.1 (#7492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-04 22:44:20 +00:00
renovate[bot] 874bef418b fix(deps): update dependency androidx.compose.material3:material3 to v1.5.0-rc01 (#7491)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-04 21:06:52 +00:00
renovate[bot] 85493b9776 chore(deps): update plugin diffplug-spotless to v8.11.0 (#7480)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-03 01:21:44 +00:00
renovate[bot] 59396cddd1 fix(deps): update dependency com.google.errorprone:error_prone_annotations to v2.52.0 (#7479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-02 19:44:48 +00:00
x-JOC f83fbb0226 fix(widgets): let the resize frame reach the screen edge horizontally (#7387)
* fix(widgets): let the resize frame reach the screen edge horizontally

The resize frame is drawn resize_frame_background_padding (24dp) outside
the widget, but the horizontal drag range clamped the frame's outer edge
to the DragLayer. When the grid sits close to the screen edge (low
workspace/widget padding, many columns) the last column could not be
reached.

When the frame already overhung the screen edge (gap + widget padding
< 24dp, which is the default), the old range did not contain 0 (left
start positive, right end negative), so the first move event snapped the
frame up to 24dp inward on either side. With half-cell resize steps that
would be enough to drop a step.

Bound the widget's edge instead of the frame's, and keep 0 inside the
range so a touch without movement never moves the frame. The vertical
range is unchanged.

* fix(widgets): count the last partial resize step when the finger hits the edge

The finger cannot travel past the screen edge, and the handle can be
grabbed up to 24dp outside the widget. With little workspace/widget
padding, the travel left for the last column can then be shorter than
RESIZE_THRESHOLD of a step.

While a left/right handle is dragged and the finger is within
resize_frame_background_padding of that screen edge, a partial step of
more than 1 - RESIZE_THRESHOLD towards the edge counts as reached. That
threshold keeps the step from being undone right after it is taken, and
it only applies in the growth direction.

* refactor(widgets): shorten resize frame LC-Notes

Comment-only change: trim the edge-clamp LC-Notes in AppWidgetResizeFrame to one or two lines. No behaviour change.
2026-11-02 15:25:39 +08:00
Jaxon WrightandClaude Opus 5.5 5a9f6e05ba fix(backup): restore into the database that gets opened (#7460)
createDatabaseHelper renamed restored.db to the IDP's dbFile but opened
the dbFile it was passed, from the DB_FILE pref. The Nova import writes
grid prefs before restoring, and hotseatColumns' reloadGrid listener can
move the IDP to an intermediate grid (e.g. launcher_6_4_5.db) first. The
restored layout then landed in a file that was never opened, the opened
file was created empty, performRestore sanitized nothing, and the next
start reset the "empty" database to the default layout. A second import
worked because the prefs no longer changed.

Rename into the file that is opened instead.

migrateDbName moves launcher.db to dbName when dbName doesn't exist yet.
With the restore now renamed into dbFile, a dbFile of launcher.db (the
5_by_5 grid) would be moved away and deleted before DatabaseHelper opens
it. Migrate first, then rename.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 15:22:05 +08:00
renovate[bot] ce6c4132a7 fix(deps): update dependency net.bytebuddy:byte-buddy to v1.18.17-jdk5 (#7475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-02 05:37:04 +00:00
renovate[bot] ff037218d4 fix(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.18.17-jdk5 (#7476)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-11-02 00:59:02 +00:00
Pun Butrach 849fec9ef6 feat: QoL improvement to suspend application usage (#7338)
* fix: Tint suspend icon

* feat: Check if icon is suspendable

* fix: Resolve app name correctly

* fix: Improve permission detection

* chore: Please the spotless lord

* fix: Apply suggestions

* chore: Apply suggestions

* chore: Apply suggestions
2026-11-01 15:08:31 +07:00
stevenandsteven-ahfu f6ee1d9b3c fix: Handle missing themed icon drawables (#7466)
Co-authored-by: steven-ahfu <4956188+steven-ahfu@users.noreply.github.com>
2026-11-01 13:46:07 +07:00
Lawnchair BotandCrowdin Bot f84b9e3564 New Crowdin translations by GitHub Action (#7470)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-11-01 00:21:50 +00:00
renovate[bot] b396f41c24 chore(deps): update plugin google-ksp to v2.3.13 (#7465)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-30 21:58:32 +00:00
caizhixingandcaizhixing 8429fbe09d fix: Crash in SettingsCache.onChange for unreadable hidden keys (#7452)
SettingsCache observes hidden Settings keys — e.g.
hide_privatespace_entry_point, which ModelInitializer registers a
listener for. Since Android S, hidden settings keys are only readable
by system apps; a query from a third-party app throws
SecurityException.

3962597e6e fixed this for the read path by catching SecurityException
in getValue(), but the ContentObserver path was missed: when the system
writes such a key, onChange() calls updateValue() on the main-thread
handler and the launcher crashes.

Skip the cache update instead, mirroring the existing guard in
getValue().

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-10-30 21:45:11 +07:00
steven c154f993c8 [Fix]: Stop platform from overriding Lawnchair's own dark theme (#7267) 2026-10-30 14:43:23 +00:00
caizhixingandcaizhixing f00bff4f50 Catch SecurityException thrown from setWallpaperOffsets (#7454)
On some OEM builds (e.g. Huawei EMUI on API <= 28), WallpaperManager
.setWallpaperOffsets() internally fetches the current wallpaper bitmap,
and WallpaperManagerService enforces READ_EXTERNAL_STORAGE on that
binder call. When the permission is not granted the call throws
SecurityException, which escaped setOffsetSafely() and fatally crashed
the launcher on every workspace page swipe.

Skip and log the offset update on affected devices instead; wallpaper
parallax simply stops updating there.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-10-30 21:40:10 +07:00
caizhixingandcaizhixing d714016ffc fix: Crash in multi-window on API 26-29 (#7453)
getMultiWindowDisplaySize() calls WindowManager.getCurrentWindowMetrics(),
added in API 30, without a version check. Lawnchair runs down to
minSdk 26, so building the multi-window device profile
(Launcher#initDeviceProfile and the fallback RecentsActivity) throws
NoSuchMethodError on Android 8-10 devices in split-screen.

Derive the bounds from the default display size below R.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-10-30 21:37:05 +07:00
Pun Butrach be56ee534f refactor: Move Lawnchair gesture vibrator to MSDL player (#7464)
* feat: Move gesture vibrator to MSDL player

* chore: Please the lord Spotless
2026-10-30 21:32:40 +07:00
Pun Butrach f9b99e2da2 fix: Icon not responding to system accent changes (#7370) 2026-10-30 16:33:00 +07:00
caizhixingandcaizhixing c5c5a42ca4 fix: crash when dismissing a task with haptics on API 26-29 (#7451)
VibratorWrapper.vibrate(primitiveId, ...) calls
Vibrator.areAllPrimitivesSupported() and builds a
VibrationEffect.Composition, both added in API 30, without a version
check. Lawnchair runs down to minSdk 26, so dismissing a task in
Recents — TaskViewTouchControllerDeprecated passes PRIMITIVE_TICK, a
non-negative id — throws NoSuchMethodError and crashes the launcher
on Android 8-10 devices.

Fall back to the plain fallback effect below R, mirroring the existing
ATLEAST_S guard in vibrateForTaskbarUnstash() and the ATLEAST_Q branch
that already builds EFFECT_CLICK.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-10-30 01:33:33 +08:00
renovate[bot] 2d07299867 chore(deps): update agp to v9.5.0 (#7458)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-28 18:28:13 +00:00
Pun Butrach 15ebe41583 refactor: Hide battery charging speeds behind code flag (#7449) 2026-10-27 16:57:10 +00:00
caizhixingandcaizhixing 1d68a13644 fix: Fall back to the default mask when config_icon_mask is unparsable (#7424)
config_icon_mask is a framework resource that ROM overlays can replace.
When its value is not valid path data (seen in the wild with a line break
inside a coordinate), PathParser throws during Launcher onCreate and the
launcher enters a crash loop. Parse the mask defensively and fall back
to the platform default mask, mirroring the existing guard around
GenericPathShape in the same file.

Co-authored-by: caizhixing <17589399+caizhixing03@user.noreply.gitee.com>
2026-10-27 23:50:02 +07:00
Pun Butrach 7436e7408d refactor: Pass swipe down gesture notifications panel to native touch controller (#7448)
* refactor: Pass swipe down gesture over to native touch controller

* chore: Spotlessified

* fix: Apply reviewer
2026-10-27 22:34:29 +07:00