import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
-import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
-import moe.banana.support.ToastCompat;
-
public class U {
private U() {}
}
@TargetApi(Build.VERSION_CODES.M)
- public static void showPermissionDialog(final Context context) {
+ public static AlertDialog showPermissionDialog(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.permission_dialog_title)
.setMessage(R.string.permission_dialog_message)
AlertDialog dialog = builder.create();
dialog.show();
dialog.setCancelable(false);
+
+ return dialog;
}
public static void showErrorDialog(final Context context, String appopCmd) {
if(mDevicePolicyManager.isAdminActive(component))
mDevicePolicyManager.lockNow();
else {
- Intent intent = new Intent(context, DummyActivity.class);
- intent.putExtra("device_admin", true);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
+ launchApp(context, () -> {
+ Intent intent = new Intent(context, DummyActivity.class);
+ intent.putExtra("device_admin", true);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ });
}
}
intent.putExtra("action", action);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
} else {
- Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ launchApp(context, () -> {
+ Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- showToastLong(context, R.string.enable_accessibility);
- } catch (ActivityNotFoundException e) {
- showToast(context, R.string.lock_device_not_supported);
- }
+ try {
+ context.startActivity(intent);
+ showToastLong(context, R.string.enable_accessibility);
+ } catch (ActivityNotFoundException e) {
+ showToast(context, R.string.lock_device_not_supported);
+ }
+ });
}
}
public static void showToast(Context context, String message, int length) {
cancelToast();
- ToastCompat toast = ToastCompat.makeText(context.getApplicationContext(), message, length);
+ ToastInterface toast;
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1
+ || BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID))
+ toast = new ToastFrameworkImpl(context, message, length);
+ else
+ toast = new ToastCompatImpl(context, message, length);
+
toast.show();
ToastHelper.getInstance().setLastToast(toast);
}
- public static void cancelToast() {
- ToastCompat toast = ToastHelper.getInstance().getLastToast();
+ private static void cancelToast() {
+ ToastInterface toast = ToastHelper.getInstance().getLastToast();
if(toast != null) toast.cancel();
}
final boolean launchedFromTaskbar,
final boolean openInNewWindow,
final ShortcutInfo shortcut) {
+ launchApp(context, launchedFromTaskbar, () -> continueLaunchingApp(context, packageName, componentName, userId,
+ windowSize, launchedFromTaskbar, openInNewWindow, shortcut));
+ }
+
+ public static void launchApp(Context context, Runnable runnable) {
+ launchApp(context, true, runnable);
+ }
+
+ private static void launchApp(Context context, boolean launchedFromTaskbar, Runnable runnable) {
SharedPreferences pref = getSharedPreferences(context);
FreeformHackHelper helper = FreeformHackHelper.getInstance();
+ boolean specialLaunch = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ && FreeformHackHelper.getInstance().isInFreeformWorkspace()
+ && MenuHelper.getInstance().isContextMenuOpen();
+
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& pref.getBoolean("freeform_hack", false)
- && !helper.isInFreeformWorkspace()) {
+ && (!helper.isInFreeformWorkspace() || specialLaunch)) {
new Handler().postDelayed(() -> {
startFreeformHack(context, true, launchedFromTaskbar);
- new Handler().postDelayed(() -> continueLaunchingApp(context, packageName, componentName, userId,
- windowSize, launchedFromTaskbar, openInNewWindow, shortcut), helper.isFreeformHackActive() ? 0 : 100);
+ new Handler().postDelayed(runnable, helper.isFreeformHackActive() ? 0 : 100);
}, launchedFromTaskbar ? 0 : 100);
} else
- continueLaunchingApp(context, packageName, componentName, userId,
- windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
+ runnable.run();
}
@SuppressWarnings("deprecation")
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if(FreeformHackHelper.getInstance().isInFreeformWorkspace()
- && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
- && !isOPreview())
+ && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1)
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
if(launchedFromTaskbar) {
}
ApplicationType type = getApplicationType(context, packageName);
- boolean specialLaunch = isOPreview() && FreeformHackHelper.getInstance().isInFreeformWorkspace() && openInNewWindow;
if(windowSize == null)
windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N
|| !pref.getBoolean("freeform_hack", false)
|| windowSize.equals("standard")) {
- launchStandard(context, intent, userId, shortcut, type, specialLaunch);
+ launchStandard(context, intent, userId, shortcut, type);
} else switch(windowSize) {
case "large":
- launchMode1(context, intent, userId, shortcut, type, specialLaunch);
+ launchMode1(context, intent, userId, shortcut, type);
break;
case "fullscreen":
- launchMode2(context, intent, MAXIMIZED, userId, shortcut, type, specialLaunch);
+ launchMode2(context, intent, MAXIMIZED, userId, shortcut, type);
break;
case "half_left":
- launchMode2(context, intent, LEFT, userId, shortcut, type, specialLaunch);
+ launchMode2(context, intent, LEFT, userId, shortcut, type);
break;
case "half_right":
- launchMode2(context, intent, RIGHT, userId, shortcut, type, specialLaunch);
+ launchMode2(context, intent, RIGHT, userId, shortcut, type);
break;
case "phone_size":
- launchMode3(context, intent, userId, shortcut, type, specialLaunch);
+ launchMode3(context, intent, userId, shortcut, type);
break;
}
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
}
- private static void launchStandard(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type, boolean specialLaunch) {
+ private static void launchStandard(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) {
Bundle bundle = Build.VERSION.SDK_INT < Build.VERSION_CODES.N ? null : getActivityOptions(type).toBundle();
if(shortcut == null) {
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
try {
- startActivity(context, intent, bundle, specialLaunch);
+ context.startActivity(intent, bundle);
} catch (ActivityNotFoundException e) {
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
} else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
} else
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- private static void launchMode1(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type, boolean specialLaunch) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ private static void launchMode1(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
- int width1 = display.getWidth() / 8;
- int width2 = display.getWidth() - width1;
- int height1 = display.getHeight() / 8;
- int height2 = display.getHeight() - height1;
+ int width1 = metrics.widthPixels / 8;
+ int width2 = metrics.widthPixels - width1;
+ int height1 = metrics.heightPixels / 8;
+ int height2 = metrics.heightPixels - height1;
Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect(
width1,
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
try {
- startActivity(context, intent, bundle, specialLaunch);
+ context.startActivity(intent, bundle);
} catch (ActivityNotFoundException e) {
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
} else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
} else
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut, ApplicationType type, boolean specialLaunch) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
-
+ private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
+
int statusBarHeight = getStatusBarHeight(context);
String position = getTaskbarPosition(context);
boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
int left = launchType == RIGHT && isLandscape
- ? display.getWidth() / 2
+ ? metrics.widthPixels / 2
: 0;
int top = launchType == RIGHT && isPortrait
- ? display.getHeight() / 2
+ ? metrics.heightPixels / 2
: statusBarHeight;
int right = launchType == LEFT && isLandscape
- ? display.getWidth() / 2
- : display.getWidth();
+ ? metrics.widthPixels / 2
+ : metrics.widthPixels;
int bottom = launchType == LEFT && isPortrait
- ? display.getHeight() / 2
- : display.getHeight();
+ ? metrics.heightPixels / 2
+ : metrics.heightPixels;
int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
try {
- startActivity(context, intent, bundle, specialLaunch);
+ context.startActivity(intent, bundle);
} catch (ActivityNotFoundException e) {
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
} else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
} else
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type, boolean specialLaunch) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
- int width1 = display.getWidth() / 2;
+ int width1 = metrics.widthPixels / 2;
int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2;
- int height1 = display.getHeight() / 2;
+ int height1 = metrics.heightPixels / 2;
int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2;
Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect(
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
try {
- startActivity(context, intent, bundle, specialLaunch);
+ context.startActivity(intent, bundle);
} catch (ActivityNotFoundException e) {
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
} else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
} else
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
long userId = userManager.getSerialNumberForUser(Process.myUserHandle());
- launchMode2(context, intent, MAXIMIZED, userId, null, ApplicationType.CONTEXT_MENU, false);
+ launchMode2(context, intent, MAXIMIZED, userId, null, ApplicationType.CONTEXT_MENU);
}
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
public static void launchAppLowerRight(Context context, Intent intent) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
try {
context.startActivity(intent, getActivityOptions(ApplicationType.FREEFORM_HACK).setLaunchBounds(new Rect(
- display.getWidth(),
- display.getHeight(),
- display.getWidth() + 1,
- display.getHeight() + 1
+ metrics.widthPixels,
+ metrics.heightPixels,
+ metrics.widthPixels + 1,
+ metrics.heightPixels + 1
)).toBundle());
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
}
public static void checkForUpdates(Context context) {
- if(!BuildConfig.DEBUG) {
- String url;
- try {
- context.getPackageManager().getPackageInfo("com.android.vending", 0);
- url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
- } catch (PackageManager.NameNotFoundException e) {
- url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
- }
+ if(!BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)) {
+ if(!BuildConfig.DEBUG) {
+ String url;
+ try {
+ context.getPackageManager().getPackageInfo("com.android.vending", 0);
+ url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
+ } catch (PackageManager.NameNotFoundException e) {
+ url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
+ }
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
- } else
- showToast(context, R.string.debug_build);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
+ } else
+ showToast(context, R.string.debug_build);
+ }
}
public static boolean launcherIsDefault(Context context) {
private static int getMaxNumOfColumns(Context context) {
SharedPreferences pref = getSharedPreferences(context);
- DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
float baseTaskbarSize = getBaseTaskbarSizeFloat(context) / metrics.density;
int numOfColumns = 0;
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
|| Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
- || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
+ || (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
+ && Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1));
}
public static boolean hasPartialFreeformSupport() {
- return Build.MANUFACTURER.equalsIgnoreCase("Samsung") || isOPreview();
+ return Build.MANUFACTURER.equalsIgnoreCase("Samsung");
}
public static boolean isServiceRunning(Context context, Class<? extends Service> cls) {
SharedPreferences.Editor editor = pref.edit();
if(!pref.getBoolean("show_background", true))
- editor.putInt("background_tint", 0).apply();
+ editor.putInt("background_tint", Color.TRANSPARENT).apply();
editor.remove("show_background");
editor.apply();
stackId = FREEFORM_WORKSPACE_STACK_ID;
break;
case CONTEXT_MENU:
- if(isOPreview()) stackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ stackId = FULLSCREEN_WORKSPACE_STACK_ID;
}
if(stackId != null) {
}
}
- @TargetApi(Build.VERSION_CODES.M)
- public static boolean isOPreview() {
- return (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) || (Build.VERSION.RELEASE.equals("O") && Build.VERSION.PREVIEW_SDK_INT > 0);
+ public static boolean isChromeOs(Context context) {
+ return context.getPackageManager().hasSystemFeature("org.chromium.arc");
}
public static boolean hasSupportLibrary(Context context) {
}
}
- private static void startActivity(Context context, Intent intent, Bundle options, boolean specialLaunch) {
- if(specialLaunch) {
- startFreeformHack(context, true, false);
- new Handler().post(() -> context.startActivity(intent, options));
- } else
- context.startActivity(intent, options);
- }
-
public static int getBaseTaskbarSize(Context context) {
return Math.round(getBaseTaskbarSizeFloat(context));
}
Settings.System.putInt(context.getContentResolver(), "navigation_bar_show", show ? 1 : 0);
} catch (Exception e) { /* Gracefully fail */ }
}
+
+ public static void initPrefs(Context context) {
+ // On smaller-screened devices, set "Grid" as the default start menu layout
+ SharedPreferences pref = getSharedPreferences(context);
+ if(context.getApplicationContext().getResources().getConfiguration().smallestScreenWidthDp < 600
+ && pref.getString("start_menu_layout", "null").equals("null")) {
+ pref.edit().putString("start_menu_layout", "grid").apply();
+ }
+
+ // Enable freeform hack automatically on supported devices
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ if(!pref.getBoolean("freeform_hack_override", false)) {
+ pref.edit()
+ .putBoolean("freeform_hack", hasFreeformSupport(context) && !hasPartialFreeformSupport())
+ .putBoolean("save_window_sizes", false)
+ .putBoolean("freeform_hack_override", true)
+ .apply();
+ } else if(!hasFreeformSupport(context)) {
+ pref.edit().putBoolean("freeform_hack", false).apply();
+
+ LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.FINISH_FREEFORM_ACTIVITY"));
+ }
+ }
+
+ // Customizations for Android-x86 devices (non-Bliss)
+ if(BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)
+ && isSystemApp(context)
+ && !pref.getBoolean("android_x86_prefs", false)) {
+ pref.edit()
+ .putString("recents_amount", "running_apps_only")
+ .putString("refresh_frequency", "0")
+ .putString("max_num_of_recents", "2147483647")
+ .putBoolean("full_length", true)
+ .putBoolean("dashboard", true)
+ .putBoolean("android_x86_prefs", true)
+ .apply();
+ }
+ }
+
+ public static DisplayMetrics getRealDisplayMetrics(Context context) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display disp = wm.getDefaultDisplay();
+
+ SharedPreferences pref = getSharedPreferences(context);
+ if(isChromeOs(context) && !pref.getBoolean("chrome_os_context_menu_fix", false))
+ disp.getRealMetrics(metrics);
+ else
+ disp.getMetrics(metrics);
+
+ return metrics;
+ }
+
+ public static int getOverlayType() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
+ : WindowManager.LayoutParams.TYPE_PHONE;
+ }
}