diff --git a/lawnchair/res/values/config.xml b/lawnchair/res/values/config.xml
index 5068dacf2e..b0ad604e69 100644
--- a/lawnchair/res/values/config.xml
+++ b/lawnchair/res/values/config.xml
@@ -89,6 +89,8 @@
false
true
false
+ false
+ false
true
false
true
diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index 959c6f4067..3639d2b400 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -233,6 +233,10 @@
Rounded Corners
Allow Overlap
+ Enforce Widget Resizing
+ Allow resizing of widgets that are constrained to a specific size
+ Remove Size Constraints
+ Remove the minimum and maximum size restrictions of widgets
Columns
diff --git a/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt b/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt
index 1f9bcba305..25841611d4 100644
--- a/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt
+++ b/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt
@@ -192,6 +192,16 @@ class PreferenceManager2 private constructor(private val context: Context) : Pre
onSet = { reloadHelper.reloadGrid() },
)
+ val forceWidgetResize = preference(
+ key = booleanPreferencesKey(name = "force_widget_resize"),
+ defaultValue = context.resources.getBoolean(R.bool.config_default_force_widget_resize),
+ )
+
+ val widgetUnlimitedSize = preference(
+ key = booleanPreferencesKey(name = "widget_unlimited_size"),
+ defaultValue = context.resources.getBoolean(R.bool.config_default_widget_unlimited_size),
+ )
+
val showStatusBar = preference(
key = booleanPreferencesKey(name = "show_status_bar"),
defaultValue = context.resources.getBoolean(R.bool.config_default_show_status_bar),
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/destinations/HomeScreenPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/destinations/HomeScreenPreferences.kt
index cfcb23c411..30b71045fb 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/destinations/HomeScreenPreferences.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/destinations/HomeScreenPreferences.kt
@@ -206,6 +206,16 @@ fun HomeScreenPreferences() {
adapter = prefs2.allowWidgetOverlap.getAdapter(),
label = stringResource(id = R.string.allow_widget_overlap),
)
+ SwitchPreference(
+ adapter = prefs2.widgetUnlimitedSize.getAdapter(),
+ label = stringResource(id = R.string.widget_unlimited_size_label),
+ description = stringResource(id = R.string.widget_unlimited_size_description),
+ )
+ SwitchPreference(
+ adapter = prefs2.forceWidgetResize.getAdapter(),
+ label = stringResource(id = R.string.force_widget_resize_label),
+ description = stringResource(id = R.string.force_widget_resize_description),
+ )
}
}
}
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 5b9646e510..74ed8f7b98 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -42,10 +42,12 @@ import com.android.launcher3.views.ArrowTipView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.util.WidgetSizes;
+import com.patrykmichalik.opto.core.PreferenceExtensionsKt;
import java.util.ArrayList;
import java.util.List;
+import app.lawnchair.preferences2.PreferenceManager2;
import app.lawnchair.theme.color.ColorTokens;
import app.lawnchair.theme.drawable.DrawableTokens;
@@ -186,6 +188,10 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
}
public static void showForWidget(LauncherAppWidgetHostView widget, CellLayout cellLayout) {
+ PreferenceManager2 pref2 = PreferenceManager2.getInstance(widget.getContext());
+ boolean force = PreferenceExtensionsKt.firstBlocking(pref2.getForceWidgetResize());
+ boolean unlimited = PreferenceExtensionsKt.firstBlocking(pref2.getWidgetUnlimitedSize());
+
Launcher launcher = Launcher.getLauncher(cellLayout.getContext());
AbstractFloatingView.closeAllOpenViews(launcher);
@@ -202,7 +208,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
gd.setCornerRadius(enforcedCornerRadius);
}
}
- frame.setupForWidget(widget, cellLayout, dl);
+ frame.setupForWidget(widget, cellLayout, dl, force, unlimited);
((DragLayer.LayoutParams) frame.getLayoutParams()).customPosition = true;
dl.addView(frame);
@@ -211,27 +217,45 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
}
private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
- DragLayer dragLayer) {
+ DragLayer dragLayer, boolean force, boolean unlimited) {
mCellLayout = cellLayout;
mWidgetView = widgetView;
LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo) widgetView.getAppWidgetInfo();
mDragLayer = dragLayer;
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(cellLayout.getContext());
- mMinHSpan = info.minSpanX;
- mMinVSpan = info.minSpanY;
- mMaxHSpan = info.maxSpanX;
- mMaxVSpan = info.maxSpanY;
+ int resizeMode;
+ if (force) {
+ resizeMode = AppWidgetProviderInfo.RESIZE_BOTH;
+ } else {
+ resizeMode = info.resizeMode;
+ }
+ if (unlimited) {
+ mMinHSpan = 1;
+ mMinVSpan = 1;
+ mMaxHSpan = idp.numColumns;
+ mMaxVSpan = idp.numRows;
+
+ // If widget is resizable in any direction, make it resizable in both
+ if (resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+ resizeMode = AppWidgetProviderInfo.RESIZE_BOTH;
+ }
+ } else {
+ mMinHSpan = info.minSpanX;
+ mMinVSpan = info.minSpanY;
+ mMaxHSpan = info.maxSpanX;
+ mMaxVSpan = info.maxSpanY;
+ }
// Only show resize handles for the directions in which resizing is possible.
- InvariantDeviceProfile idp = LauncherAppState.getIDP(cellLayout.getContext());
- mVerticalResizeActive = (info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0
+ mVerticalResizeActive = (resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0
&& mMinVSpan < idp.numRows && mMaxVSpan > 1
&& mMinVSpan < mMaxVSpan;
if (!mVerticalResizeActive) {
mDragHandles[INDEX_TOP].setVisibility(GONE);
mDragHandles[INDEX_BOTTOM].setVisibility(GONE);
}
- mHorizontalResizeActive = (info.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0
+ mHorizontalResizeActive = (resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0
&& mMinHSpan < idp.numColumns && mMaxHSpan > 1
&& mMinHSpan < mMaxHSpan;
if (!mHorizontalResizeActive) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 17e637a844..d9556dab65 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2131,6 +2131,7 @@ public class Workspace extends PagedView
boolean snappedToNewPage = false;
boolean resizeOnDrop = false;
Runnable onCompleteRunnable = null;
+ boolean forceWidgetResize = PreferenceExtensionsKt.firstBlocking(mPreferenceManager2.getForceWidgetResize());
if (d.dragSource != this || mDragInfo == null) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1] };
@@ -2252,7 +2253,7 @@ public class Workspace extends PagedView
// We post this call so that the widget has a chance to be placed
// in its final location
onCompleteRunnable = getWidgetResizeFrameRunnable(options,
- (LauncherAppWidgetHostView) cell, dropTargetLayout);
+ (LauncherAppWidgetHostView) cell, dropTargetLayout, forceWidgetResize);
}
mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId,
lp.getCellX(), lp.getCellY(), item.spanX, item.spanY);
@@ -2281,7 +2282,7 @@ public class Workspace extends PagedView
if (pageIsVisible) {
onCompleteRunnable = getWidgetResizeFrameRunnable(options,
- (LauncherAppWidgetHostView) cell, cellLayout);
+ (LauncherAppWidgetHostView) cell, cellLayout, forceWidgetResize);
}
}
}
@@ -2346,10 +2347,10 @@ public class Workspace extends PagedView
@Nullable
private Runnable getWidgetResizeFrameRunnable(DragOptions options,
- LauncherAppWidgetHostView hostView, CellLayout cellLayout) {
+ LauncherAppWidgetHostView hostView, CellLayout cellLayout, boolean force) {
AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
- if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
- && !options.isAccessibleDrag) {
+ boolean shouldResize = (pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) || force;
+ if (pInfo != null && shouldResize && !options.isAccessibleDrag) {
return () -> {
if (!isPageInTransition()) {
AppWidgetResizeFrame.showForWidget(hostView, cellLayout);