diff --git a/Omega/res/values/strings.xml b/Omega/res/values/strings.xml
index 16f5855e1d..96c2527d26 100644
--- a/Omega/res/values/strings.xml
+++ b/Omega/res/values/strings.xml
@@ -51,6 +51,7 @@
Dock Hide
Hide Labels
+ Colored icons
Show Search Bar
diff --git a/Omega/res/xml/custom_widgets.xml b/Omega/res/xml/custom_widgets.xml
new file mode 100644
index 0000000000..9dc24ab74e
--- /dev/null
+++ b/Omega/res/xml/custom_widgets.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Omega/res/xml/omega_preferences_dock.xml b/Omega/res/xml/omega_preferences_dock.xml
index 3c54e759be..bf87ab9f94 100644
--- a/Omega/res/xml/omega_preferences_dock.xml
+++ b/Omega/res/xml/omega_preferences_dock.xml
@@ -18,8 +18,8 @@
@@ -30,4 +30,18 @@
android:persistent="true"
android:title="@string/title__dock_hide_labels"
app:iconSpaceReserved="false" />
+
\ No newline at end of file
diff --git a/Omega/src/com/saggitt/omega/OmegaPreferences.kt b/Omega/src/com/saggitt/omega/OmegaPreferences.kt
index a63a8f9283..e37b0462b5 100644
--- a/Omega/src/com/saggitt/omega/OmegaPreferences.kt
+++ b/Omega/src/com/saggitt/omega/OmegaPreferences.kt
@@ -88,12 +88,14 @@ class OmegaPreferences(val context: Context) : SharedPreferences.OnSharedPrefere
val homeLabelRows get() = if (homeMultilineLabel) 2 else 1
/* --DOCK-- */
- var dockHide by BooleanPref("pref_key__hide_hotseat", false, recreate)
+ var dockHide by BooleanPref("pref_hideHotseat", false, recreate)
val dockTextScale by FloatPref("pref_dockTextScale", -1f, restart)
private val dockMultilineLabel by BooleanPref("pref_dockIconLabelsInTwoLines", false, recreate)
val dockLabelRows get() = if (dockMultilineLabel) 2 else 1
val hideDockLabels by BooleanPref("pref_hideDockLabels", true, restart)
var dockScale by FloatPref("pref_dockScale", -1f, recreate)
+ var dockSearchBarPref by BooleanPref("pref_dockSearchBar", false, recreate)
+ inline val dockSearchBar get() = !dockHide && dockSearchBarPref
/* --THEME-- */
var launcherTheme by StringIntPref("pref_launcherTheme", 1) { ThemeManager.getInstance(context).updateTheme() }
diff --git a/Omega/src/com/saggitt/omega/qsb/HotseatQsbWidget.java b/Omega/src/com/saggitt/omega/qsb/HotseatQsbWidget.java
index b0067fc29a..f0c719c29e 100644
--- a/Omega/src/com/saggitt/omega/qsb/HotseatQsbWidget.java
+++ b/Omega/src/com/saggitt/omega/qsb/HotseatQsbWidget.java
@@ -65,7 +65,7 @@ public HotseatQsbWidget(Context context, AttributeSet attributeSet, int i) {
static void a(HotseatQsbWidget hotseatQsbWidget) {
if (hotseatQsbWidget.mIsGoogleColored != hotseatQsbWidget.isGoogleColored()) {
hotseatQsbWidget.mIsGoogleColored = !hotseatQsbWidget.mIsGoogleColored;
- hotseatQsbWidget.onChangeListener();
+ hotseatQsbWidget.onChange();
}
}
@@ -105,6 +105,9 @@ public void setWidgetMode(boolean widgetMode) {
}
protected void onAttachedToWindow() {
+ Utilities.getOmegaPrefs(getContext())
+ .addOnPreferenceChangeListener(this, KEY_DOCK_COLORED_GOOGLE, KEY_DOCK_SEARCHBAR);
+
dW();
super.onAttachedToWindow();
Ds.addListener(this);
@@ -114,6 +117,9 @@ protected void onAttachedToWindow() {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ Utilities.getOmegaPrefs(getContext())
+ .removeOnPreferenceChangeListener(this, KEY_DOCK_COLORED_GOOGLE,
+ KEY_DOCK_SEARCHBAR);
Ds.removeListener(this);
}
@@ -121,10 +127,10 @@ protected void onDetachedFromWindow() {
public void onValueChanged(@NotNull String key, @NotNull OmegaPreferences prefs, boolean force) {
if (key.equals(KEY_DOCK_COLORED_GOOGLE)) {
mIsGoogleColored = isGoogleColored();
- onChangeListener();
+ onChange();
} else if (!widgetMode && (key.equals(KEY_DOCK_SEARCHBAR) || key.equals(KEY_DOCK_HIDE))) {
- //boolean visible = prefs.getDockSearchBar() && !prefs.getDockHide();
- //setVisibility(visible ? View.VISIBLE : View.GONE);
+ boolean visible = prefs.getDockSearchBar() && !prefs.getDockHide();
+ setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
@@ -138,7 +144,7 @@ protected Drawable getMicIcon() {
return getMicIcon(mIsGoogleColored);
}
- public final void onChangeListener() {
+ public final void onChange() {
removeAllViews();
setColors();
dW();
@@ -324,9 +330,4 @@ public void setAlpha(float alpha) {
super.setAlpha(alpha);
mLauncher.findViewById(R.id.scrim_view).invalidate();
}
-
- @Override
- public void onChange() {
-
- }
}
diff --git a/Omega/src/com/saggitt/omega/qsb/QsbConfiguration.java b/Omega/src/com/saggitt/omega/qsb/QsbConfiguration.java
index 044f77d15f..3e45c6902e 100644
--- a/Omega/src/com/saggitt/omega/qsb/QsbConfiguration.java
+++ b/Omega/src/com/saggitt/omega/qsb/QsbConfiguration.java
@@ -32,6 +32,12 @@ private QsbConfiguration(Context context) {
}
+ private void notifyListeners() {
+ for (QsbChangeListener listener : mListeners) {
+ listener.onChange();
+ }
+ }
+
public static QsbConfiguration getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = new QsbConfiguration(context.getApplicationContext());
diff --git a/Omega/src/com/saggitt/omega/widget/CustomWidgetParser.java b/Omega/src/com/saggitt/omega/widget/CustomWidgetParser.java
new file mode 100644
index 0000000000..9018677f8b
--- /dev/null
+++ b/Omega/src/com/saggitt/omega/widget/CustomWidgetParser.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020 Omega Launcher
+ *
+ * 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.saggitt.omega.widget;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Parcel;
+import android.os.Process;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.R;
+import com.android.launcher3.widget.custom.CustomAppWidgetProviderInfo;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.launcher3.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
+
+/**
+ * Utility class to parse {@ink CustomAppWidgetProviderInfo} definitions from xml
+ */
+public class CustomWidgetParser {
+
+ private static List sCustomWidgets;
+ private static SparseArray sWidgetsIdMap;
+
+ public static List getCustomWidgets(Context context) {
+ if (sCustomWidgets == null) {
+ // Synchronization not needed as it it safe to load multiple times
+ parseCustomWidgets(context);
+ }
+
+ return sCustomWidgets;
+ }
+
+ public static int getWidgetIdForCustomProvider(Context context, ComponentName provider) {
+ if (sWidgetsIdMap == null) {
+ parseCustomWidgets(context);
+ }
+ int index = sWidgetsIdMap.indexOfValue(provider);
+ if (index >= 0) {
+ return LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - sWidgetsIdMap.keyAt(index);
+ } else {
+ return AppWidgetManager.INVALID_APPWIDGET_ID;
+ }
+ }
+
+ public static LauncherAppWidgetProviderInfo getWidgetProvider(Context context, int widgetId) {
+ if (sWidgetsIdMap == null || sCustomWidgets == null) {
+ parseCustomWidgets(context);
+ }
+ ComponentName cn = sWidgetsIdMap.get(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - widgetId);
+ for (LauncherAppWidgetProviderInfo info : sCustomWidgets) {
+ if (info.provider.equals(cn)) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ private static void parseCustomWidgets(Context context) {
+ ArrayList widgets = new ArrayList<>();
+ SparseArray idMap = new SparseArray<>();
+
+ List providers = AppWidgetManager.getInstance(context)
+ .getInstalledProvidersForProfile(Process.myUserHandle());
+ if (providers.isEmpty()) {
+ sCustomWidgets = widgets;
+ sWidgetsIdMap = idMap;
+ return;
+ }
+
+ Parcel parcel = Parcel.obtain();
+ providers.get(0).writeToParcel(parcel, 0);
+
+ try (XmlResourceParser parser = context.getResources().getXml(R.xml.custom_widgets)) {
+ final int depth = parser.getDepth();
+ int type;
+
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG) && "widget".equals(parser.getName())) {
+ TypedArray a = context.obtainStyledAttributes(
+ Xml.asAttributeSet(parser), R.styleable.CustomAppWidgetProviderInfo);
+
+ parcel.setDataPosition(0);
+ CustomAppWidgetProviderInfo info = newInfo(a, parcel, context);
+ widgets.add(info);
+ a.recycle();
+
+ idMap.put(info.providerId, info.provider);
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ parcel.recycle();
+ sCustomWidgets = widgets;
+ sWidgetsIdMap = idMap;
+ }
+
+ private static CustomAppWidgetProviderInfo newInfo(TypedArray a, Parcel parcel, Context context) {
+ int providerId = a.getInt(R.styleable.CustomAppWidgetProviderInfo_providerId, 0);
+ boolean noPadding = a.getBoolean(R.styleable.CustomAppWidgetProviderInfo_noPadding, false);
+ CustomAppWidgetProviderInfo info = new CustomAppWidgetProviderInfo(parcel, false, providerId, noPadding);
+ info.provider = new ComponentName(context.getPackageName(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
+ info.customizeTitle = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_customizeTitle, 0);
+ info.customizeScreen = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_customizeScreen, 0);
+ info.customizeHasPreview = a.getBoolean(R.styleable.CustomAppWidgetProviderInfo_customizeHasPreview, false);
+
+ info.label = a.getString(R.styleable.CustomAppWidgetProviderInfo_android_label);
+ info.initialLayout = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_initialLayout, 0);
+ info.icon = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_icon, 0);
+ info.previewImage = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_previewImage, 0);
+ info.resizeMode = a.getInt(R.styleable.CustomAppWidgetProviderInfo_android_resizeMode, 0);
+
+ info.spanX = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numColumns, 1);
+ info.spanY = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numRows, 1);
+ info.minSpanX = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numMinColumns, 1);
+ info.minSpanY = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numMinRows, 1);
+ return info;
+ }
+}
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a00ec0113f..4e9ea56f53 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -29,8 +29,8 @@
8dp
- 4dp
- 2dp
+ 8dp
+ 62dp
0dp
34dp
@@ -41,7 +41,7 @@
24dp
0dp
-
+
48dp
20dp
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index ac4396778a..85b68c8672 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -48,6 +48,8 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.custom.CustomAppWidgetProviderInfo;
+import com.saggitt.omega.widget.CustomWidgetParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -131,6 +133,7 @@ static AutoInstallsLayout get(Context context, AppWidgetHost appWidgetHost,
private static final String ATTR_CLASS_NAME = "className";
private static final String ATTR_TITLE = "title";
private static final String ATTR_SCREEN = "screen";
+ private static final String ATTR_PROVIDER_ID = "providerId";
// x and y can be specified as negative integers, in which case -1 represents the
// last row / column, -2 represents the second last, and so on.
@@ -564,6 +567,76 @@ protected int verifyAndInsert(ComponentName cn, Bundle extras) {
}
}
+ protected class CustomAppWidgetParser implements TagParser {
+
+ @Override
+ public int parseAndAdd(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ final int providerId = Integer.parseInt(getAttributeValue(parser, ATTR_PROVIDER_ID));
+ LauncherAppWidgetProviderInfo provider = null;
+
+ for (LauncherAppWidgetProviderInfo each : CustomWidgetParser.getCustomWidgets(mContext)) {
+ if (each instanceof CustomAppWidgetProviderInfo) {
+ if (((CustomAppWidgetProviderInfo) each).providerId == providerId) {
+ provider = each;
+ break;
+ }
+ }
+ }
+
+ if (provider == null) {
+ if (LOGD) Log.d(TAG, "Skipping invalid with no provider");
+ return -1;
+ }
+
+ mValues.put(Favorites.SPANX, getAttributeValue(parser, ATTR_SPAN_X));
+ mValues.put(Favorites.SPANY, getAttributeValue(parser, ATTR_SPAN_Y));
+ mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_CUSTOM_APPWIDGET);
+ mValues.put(Favorites.APPWIDGET_ID, CustomWidgetParser
+ .getWidgetIdForCustomProvider(mContext, provider.provider));
+
+ // Read the extras
+ Bundle extras = new Bundle();
+ int widgetDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > widgetDepth) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (TAG_EXTRA.equals(parser.getName())) {
+ String key = getAttributeValue(parser, ATTR_KEY);
+ String value = getAttributeValue(parser, ATTR_VALUE);
+ if (key != null && value != null) {
+ extras.putString(key, value);
+ } else {
+ throw new RuntimeException("Widget extras must have a key and value");
+ }
+ } else {
+ throw new RuntimeException("Widgets can contain only extras");
+ }
+ }
+
+ return verifyAndInsert(provider.provider, extras);
+ }
+
+ protected int verifyAndInsert(ComponentName cn, Bundle extras) {
+ mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
+ mValues.put(Favorites._ID, mCallback.generateNewItemId());
+ if (!extras.isEmpty()) {
+ mValues.put(Favorites.INTENT, new Intent().putExtras(extras).toUri(0));
+ }
+
+ int insertedId = mCallback.insertAndCheck(mDb, mValues);
+ if (insertedId < 0) {
+ return -1;
+ } else {
+ return insertedId;
+ }
+ }
+ }
+
protected class FolderParser implements TagParser {
private final ArrayMap mFolderElements;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 328332e6b2..8dc01ad7de 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -288,7 +288,7 @@ public DeviceProfile(Context context, InvariantDeviceProfile inv,
topWorkspacePadding =
res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_top_padding);
- prefs.addOnPreferenceChangeListener(this, "pref_fullWidthWidgets");
+ prefs.addOnPreferenceChangeListener(this, "pref_fullWidthWidgets", "pref_dockSearchBar");
}
@Override
@@ -301,6 +301,7 @@ public void updateDimensions() {
DisplayMetrics dm = res.getDisplayMetrics();
boolean fullWidthWidgets = Utilities.getOmegaPrefs(mContext).getAllowFullWidthWidgets();
+ boolean dockSearchBar = prefs.getDockSearchBar();
boolean dockHidden = prefs.getDockHide();
float dockScale = prefs.getDockScale();
@@ -308,8 +309,16 @@ public void updateDimensions() {
: res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
hotseatBarTopPaddingPx =
- res.getDimensionPixelSize(R.dimen.v1_dynamic_grid_hotseat_top_padding);
- int extraHotseatBottomPadding = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding);
+ res.getDimensionPixelSize(dockSearchBar ?
+ R.dimen.dynamic_grid_hotseat_top_padding :
+ R.dimen.v1_dynamic_grid_hotseat_top_padding);
+
+ int extraHotseatBottomPadding = 0; //!prefs.getDockGradientStyle() ? 0
+ // : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding);
+ hotseatBarBottomPaddingPx = extraHotseatBottomPadding
+ + res.getDimensionPixelSize(dockSearchBar ?
+ R.dimen.dynamic_grid_hotseat_bottom_padding :
+ R.dimen.v1_dynamic_grid_hotseat_bottom_padding);
hotseatBarBottomPaddingPx = extraHotseatBottomPadding
+ res.getDimensionPixelSize(
R.dimen.v1_dynamic_grid_hotseat_bottom_padding);
@@ -320,8 +329,9 @@ public void updateDimensions() {
hotseatBarSizePx = isVerticalBarLayout()
? hotseatIconSizePx + hotseatBarSidePaddingStartPx
+ hotseatBarSidePaddingEndPx
- : res.getDimensionPixelSize(
- R.dimen.dynamic_grid_hotseat_size)
+ : res.getDimensionPixelSize(dockSearchBar ?
+ R.dimen.dynamic_grid_hotseat_size :
+ R.dimen.v1_dynamic_grid_hotseat_size)
+ hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
verticalDragHandleSizePx = res.getDimensionPixelSize(
R.dimen.vertical_drag_handle_size);
@@ -374,7 +384,8 @@ public void updateDimensions() {
} else if (!isVerticalBarLayout()) {
float adjustedDockScale = (float) extraSpaceFromScale / hotseatBarSizePx + 1;
verticalDragHandleSizePx *= adjustedDockScale;
- int bottomPaddingNew = Math.max((int) (hotseatBarBottomPaddingPx * adjustedDockScale), 0);
+ int qsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
+ int bottomPaddingNew = Math.max((int) (hotseatBarBottomPaddingPx * adjustedDockScale), dockSearchBar ? qsbHeight : 0);
int difference = hotseatBarBottomPaddingPx - bottomPaddingNew;
hotseatBarTopPaddingPx -= difference;
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 6785397481..8453b1fd0e 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -31,6 +31,7 @@
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.views.Transposable;
+import com.saggitt.omega.OmegaPreferences;
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable, Transposable {
@@ -58,6 +59,23 @@ int getCellYFromOrder(int rank) {
return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0;
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ OmegaPreferences prefs = Utilities.getOmegaPrefs(getContext());
+ if (prefs.getDockHide()) {
+ setVisibility(GONE);
+ } else if (prefs.getDockSearchBar()) {
+ inflate(getContext(), R.layout.search_container_hotseat, this);
+ } else {
+ View v = this.findViewById(R.id.search_container_hotseat);
+ if (v != null) {
+ removeView(v);
+ }
+ }
+ }
+
public void resetLayout(boolean hasVerticalHotseat) {
removeAllViewsInLayout();
mHasVerticalHotseat = hasVerticalHotseat;
diff --git a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
index d7bff8c06f..fbf37d094e 100644
--- a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
@@ -73,8 +73,8 @@ public String toString() {
return "WidgetProviderInfo(" + provider + ")";
}
- protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf,
- int providerId, boolean noPadding) {
+ public CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf,
+ int providerId, boolean noPadding) {
super(parcel);
if (readSelf) {
this.providerId = parcel.readInt();