mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-18 18:28:20 +00:00
Load widgets in wallpaper app launcher preview
Test: Widgets in wallpaper app launcher preview rendered Bug: 185306338 Change-Id: I38569d2ff0b64ba55eb188afa42fba4100aae7ff
This commit is contained in:
@@ -26,6 +26,7 @@ import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Fragment;
|
||||
import android.appwidget.AppWidgetHost;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
@@ -83,6 +84,8 @@ import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.BaseLauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHost;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.NavigableAppWidgetHostView;
|
||||
import com.android.launcher3.widget.custom.CustomWidgetManager;
|
||||
@@ -202,6 +205,7 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
private final InsettableFrameLayout mRootView;
|
||||
private final Hotseat mHotseat;
|
||||
private final CellLayout mWorkspace;
|
||||
private final AppWidgetHost mAppWidgetHost;
|
||||
|
||||
public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) {
|
||||
super(context);
|
||||
@@ -255,6 +259,10 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
mDp.workspacePadding.top,
|
||||
mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
|
||||
mDp.workspacePadding.bottom);
|
||||
|
||||
mAppWidgetHost = FeatureFlags.WIDGETS_IN_LAUNCHER_PREVIEW.get()
|
||||
? new LauncherPreviewAppWidgetHost(context)
|
||||
: null;
|
||||
}
|
||||
|
||||
/** Populate preview and render it. */
|
||||
@@ -354,14 +362,20 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
|
||||
private void inflateAndAddWidgets(
|
||||
LauncherAppWidgetInfo info, LauncherAppWidgetProviderInfo providerInfo) {
|
||||
AppWidgetHostView view = new NavigableAppWidgetHostView(this) {
|
||||
@Override
|
||||
protected boolean shouldAllowDirectClick() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
view.setAppWidget(-1, providerInfo);
|
||||
view.updateAppWidget(null);
|
||||
AppWidgetHostView view;
|
||||
if (FeatureFlags.WIDGETS_IN_LAUNCHER_PREVIEW.get()) {
|
||||
view = mAppWidgetHost.createView(mContext, info.appWidgetId, providerInfo);
|
||||
} else {
|
||||
view = new NavigableAppWidgetHostView(this) {
|
||||
@Override
|
||||
protected boolean shouldAllowDirectClick() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
view.setAppWidget(-1, providerInfo);
|
||||
view.updateAppWidget(null);
|
||||
}
|
||||
|
||||
view.setTag(info);
|
||||
addInScreenFromBind(view, info);
|
||||
}
|
||||
@@ -477,4 +491,31 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
|
||||
view.layout(0, 0, width, height);
|
||||
}
|
||||
|
||||
private class LauncherPreviewAppWidgetHost extends AppWidgetHost {
|
||||
|
||||
private LauncherPreviewAppWidgetHost(Context context) {
|
||||
super(context, LauncherAppWidgetHost.APPWIDGET_HOST_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AppWidgetHostView onCreateView(
|
||||
Context context,
|
||||
int appWidgetId,
|
||||
AppWidgetProviderInfo appWidget) {
|
||||
return new LauncherPreviewAppWidgetHostView(LauncherPreviewRenderer.this);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LauncherPreviewAppWidgetHostView extends BaseLauncherAppWidgetHostView {
|
||||
|
||||
private LauncherPreviewAppWidgetHostView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldAllowDirectClick() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Executors;
|
||||
|
||||
/**
|
||||
* Launcher AppWidgetHostView with support for rounded corners and a fallback View.
|
||||
*/
|
||||
public abstract class BaseLauncherAppWidgetHostView extends NavigableAppWidgetHostView {
|
||||
|
||||
protected final LayoutInflater mInflater;
|
||||
|
||||
private final Rect mEnforcedRectangle = new Rect();
|
||||
private final float mEnforcedCornerRadius;
|
||||
private final ViewOutlineProvider mCornerRadiusEnforcementOutline = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
if (mEnforcedRectangle.isEmpty() || mEnforcedCornerRadius <= 0) {
|
||||
outline.setEmpty();
|
||||
} else {
|
||||
outline.setRoundRect(mEnforcedRectangle, mEnforcedCornerRadius);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public BaseLauncherAppWidgetHostView(Context context) {
|
||||
super(context);
|
||||
|
||||
setExecutor(Executors.THREAD_POOL_EXECUTOR);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View getErrorView() {
|
||||
return mInflater.inflate(R.layout.appwidget_error, this, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fall back to error layout instead of showing widget.
|
||||
*/
|
||||
public void switchToErrorView() {
|
||||
// Update the widget with 0 Layout id, to reset the view to error view.
|
||||
updateAppWidget(new RemoteViews(getAppWidgetInfo().provider.getPackageName(), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
try {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
} catch (final RuntimeException e) {
|
||||
post(this::switchToErrorView);
|
||||
}
|
||||
|
||||
enforceRoundedCorners();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void resetRoundedCorners() {
|
||||
setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
||||
setClipToOutline(false);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void enforceRoundedCorners() {
|
||||
if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled()) {
|
||||
resetRoundedCorners();
|
||||
return;
|
||||
}
|
||||
View background = RoundedCornerEnforcement.findBackground(this);
|
||||
if (background == null
|
||||
|| RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
|
||||
resetRoundedCorners();
|
||||
return;
|
||||
}
|
||||
RoundedCornerEnforcement.computeRoundedRectangle(this,
|
||||
background,
|
||||
mEnforcedRectangle);
|
||||
setOutlineProvider(mCornerRadiusEnforcementOutline);
|
||||
setClipToOutline(true);
|
||||
}
|
||||
|
||||
/** Returns the corner radius currently enforced, in pixels. */
|
||||
public float getEnforcedCornerRadius() {
|
||||
return mEnforcedCornerRadius;
|
||||
}
|
||||
|
||||
/** Returns true if the corner radius are enforced for this App Widget. */
|
||||
public boolean hasEnforcedCornerRadius() {
|
||||
return getClipToOutline();
|
||||
}
|
||||
}
|
||||
@@ -20,19 +20,16 @@ import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Advanceable;
|
||||
@@ -40,7 +37,6 @@ import android.widget.RemoteViews;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.CheckLongPressHelper;
|
||||
import com.android.launcher3.Launcher;
|
||||
@@ -51,7 +47,6 @@ import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.BaseDragLayer.TouchCompleteListener;
|
||||
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
|
||||
@@ -61,7 +56,7 @@ import java.util.List;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
|
||||
implements TouchCompleteListener, View.OnLongClickListener,
|
||||
LocalColorExtractor.Listener {
|
||||
|
||||
@@ -76,8 +71,6 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
// Maximum duration for which updates can be deferred.
|
||||
private static final long UPDATE_LOCK_TIMEOUT_MILLIS = 1000;
|
||||
|
||||
protected final LayoutInflater mInflater;
|
||||
|
||||
private final CheckLongPressHelper mLongPressHelper;
|
||||
protected final Launcher mLauncher;
|
||||
private final Workspace mWorkspace;
|
||||
@@ -101,18 +94,6 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
private final Rect mWidgetSizeAtDrag = new Rect();
|
||||
|
||||
private final RectF mTempRectF = new RectF();
|
||||
private final Rect mEnforcedRectangle = new Rect();
|
||||
private final float mEnforcedCornerRadius;
|
||||
private final ViewOutlineProvider mCornerRadiusEnforcementOutline = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
if (mEnforcedRectangle.isEmpty() || mEnforcedCornerRadius <= 0) {
|
||||
outline.setEmpty();
|
||||
} else {
|
||||
outline.setRoundRect(mEnforcedRectangle, mEnforcedCornerRadius);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final Object mUpdateLock = new Object();
|
||||
private final ViewGroupFocusHelper mDragLayerRelativeCoordinateHelper;
|
||||
private long mDeferUpdatesUntilMillis = 0;
|
||||
@@ -123,18 +104,15 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mWorkspace = mLauncher.getWorkspace();
|
||||
mLongPressHelper = new CheckLongPressHelper(this, this);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
|
||||
setBackgroundResource(R.drawable.widget_internal_focus_bg);
|
||||
|
||||
setExecutor(Executors.THREAD_POOL_EXECUTOR);
|
||||
if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
|
||||
setOnLightBackground(true);
|
||||
}
|
||||
mColorExtractor = LocalColorExtractor.newInstance(getContext());
|
||||
mColorExtractor.setListener(this);
|
||||
|
||||
mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(getContext());
|
||||
mDragLayerRelativeCoordinateHelper = new ViewGroupFocusHelper(mLauncher.getDragLayer());
|
||||
}
|
||||
|
||||
@@ -165,11 +143,6 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View getErrorView() {
|
||||
return mInflater.inflate(R.layout.appwidget_error, this, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAppWidget(RemoteViews remoteViews) {
|
||||
synchronized (mUpdateLock) {
|
||||
@@ -304,34 +277,17 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
}
|
||||
}
|
||||
|
||||
public void switchToErrorView() {
|
||||
// Update the widget with 0 Layout id, to reset the view to error view.
|
||||
updateAppWidget(new RemoteViews(getAppWidgetInfo().provider.getPackageName(), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
try {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
} catch (final RuntimeException e) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switchToErrorView();
|
||||
}
|
||||
});
|
||||
}
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
mIsScrollable = checkScrollableRecursively(this);
|
||||
if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
|
||||
|
||||
LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
|
||||
mDragLayerRelativeCoordinateHelper.viewToRect(this, mCurrentWidgetSize);
|
||||
updateColorExtraction(mCurrentWidgetSize,
|
||||
mWorkspace.getPageIndexForScreenId(info.screenId));
|
||||
}
|
||||
|
||||
enforceRoundedCorners();
|
||||
}
|
||||
|
||||
/** Starts the drag mode. */
|
||||
@@ -502,40 +458,4 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void resetRoundedCorners() {
|
||||
setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
||||
setClipToOutline(false);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void enforceRoundedCorners() {
|
||||
if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled()) {
|
||||
resetRoundedCorners();
|
||||
return;
|
||||
}
|
||||
View background = RoundedCornerEnforcement.findBackground(this);
|
||||
if (background == null
|
||||
|| RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
|
||||
resetRoundedCorners();
|
||||
return;
|
||||
}
|
||||
RoundedCornerEnforcement.computeRoundedRectangle(this,
|
||||
background,
|
||||
mEnforcedRectangle);
|
||||
setOutlineProvider(mCornerRadiusEnforcementOutline);
|
||||
setClipToOutline(true);
|
||||
}
|
||||
|
||||
/** Returns the corner radius currently enforced, in pixels. */
|
||||
public float getEnforcedCornerRadius() {
|
||||
return mEnforcedCornerRadius;
|
||||
}
|
||||
|
||||
/** Returns true if the corner radius are enforced for this App Widget. */
|
||||
public boolean hasEnforcedCornerRadius() {
|
||||
return getClipToOutline();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user