1 /* Copyright 2016 Braden Farmer
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 package com.farmerbb.taskbar.service;
18 import android.annotation.SuppressLint;
19 import android.annotation.TargetApi;
20 import android.app.SearchManager;
21 import android.app.Service;
22 import android.content.ActivityNotFoundException;
23 import android.content.BroadcastReceiver;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.SharedPreferences;
29 import android.content.pm.LauncherActivityInfo;
30 import android.content.pm.LauncherApps;
31 import android.content.pm.PackageManager;
32 import android.content.res.Configuration;
33 import android.graphics.PixelFormat;
34 import android.graphics.Rect;
35 import android.graphics.drawable.Drawable;
36 import android.net.Uri;
37 import android.os.Build;
38 import android.os.Handler;
39 import android.os.IBinder;
40 import android.os.UserHandle;
41 import android.os.UserManager;
42 import android.provider.Settings;
43 import android.support.v4.content.LocalBroadcastManager;
44 import android.support.v7.widget.SearchView;
45 import android.util.DisplayMetrics;
46 import android.util.Patterns;
47 import android.view.ContextThemeWrapper;
48 import android.view.Gravity;
49 import android.view.LayoutInflater;
50 import android.view.MotionEvent;
51 import android.view.View;
52 import android.view.ViewGroup;
53 import android.view.WindowManager;
54 import android.view.inputmethod.EditorInfo;
55 import android.view.inputmethod.InputMethodManager;
56 import android.webkit.URLUtil;
57 import android.widget.EditText;
58 import android.widget.FrameLayout;
59 import android.widget.GridView;
60 import android.widget.LinearLayout;
61 import android.widget.ListAdapter;
62 import android.widget.TextView;
64 import com.farmerbb.taskbar.R;
65 import com.farmerbb.taskbar.activity.ContextMenuActivity;
66 import com.farmerbb.taskbar.activity.dark.ContextMenuActivityDark;
67 import com.farmerbb.taskbar.activity.InvisibleActivity;
68 import com.farmerbb.taskbar.activity.InvisibleActivityAlt;
69 import com.farmerbb.taskbar.adapter.StartMenuAdapter;
70 import com.farmerbb.taskbar.util.AppEntry;
71 import com.farmerbb.taskbar.util.ApplicationType;
72 import com.farmerbb.taskbar.util.Blacklist;
73 import com.farmerbb.taskbar.util.FreeformHackHelper;
74 import com.farmerbb.taskbar.util.IconCache;
75 import com.farmerbb.taskbar.util.LauncherHelper;
76 import com.farmerbb.taskbar.util.MenuHelper;
77 import com.farmerbb.taskbar.util.CompatUtils;
78 import com.farmerbb.taskbar.util.TopApps;
79 import com.farmerbb.taskbar.util.U;
80 import com.farmerbb.taskbar.widget.StartMenuLayout;
82 import java.text.Collator;
83 import java.util.ArrayList;
84 import java.util.Collections;
85 import java.util.Comparator;
86 import java.util.List;
88 public class StartMenuService extends Service {
90 private WindowManager windowManager;
91 private StartMenuLayout layout;
92 private GridView startMenu;
93 private SearchView searchView;
94 private TextView textView;
95 private PackageManager pm;
97 private Handler handler;
98 private Thread thread;
100 private boolean shouldShowSearchBox = false;
101 private boolean hasSubmittedQuery = false;
103 private int layoutId = R.layout.start_menu_left;
105 private List<String> currentStartMenuIds = new ArrayList<>();
107 private View.OnClickListener ocl = view -> toggleStartMenu();
109 private BroadcastReceiver toggleReceiver = new BroadcastReceiver() {
111 public void onReceive(Context context, Intent intent) {
116 private BroadcastReceiver showSpaceReceiver = new BroadcastReceiver() {
118 public void onReceive(Context context, Intent intent) {
119 layout.findViewById(R.id.start_menu_space).setVisibility(View.VISIBLE);
123 private BroadcastReceiver hideSpaceReceiver = new BroadcastReceiver() {
125 public void onReceive(Context context, Intent intent) {
126 layout.findViewById(R.id.start_menu_space).setVisibility(View.GONE);
130 private BroadcastReceiver hideReceiver = new BroadcastReceiver() {
132 public void onReceive(Context context, Intent intent) {
137 private BroadcastReceiver hideReceiverNoReset = new BroadcastReceiver() {
139 public void onReceive(Context context, Intent intent) {
140 hideStartMenu(false);
144 private BroadcastReceiver resetReceiver = new BroadcastReceiver() {
146 public void onReceive(Context context, Intent intent) {
147 startMenu.setSelection(0);
151 private Comparator<LauncherActivityInfo> comparator = (ai1, ai2) -> {
156 label1 = ai1.getLabel().toString();
157 label2 = ai2.getLabel().toString();
158 } catch (OutOfMemoryError e) {
161 label1 = ai1.getApplicationInfo().packageName;
162 label2 = ai2.getApplicationInfo().packageName;
165 return Collator.getInstance().compare(label1, label2);
169 public IBinder onBind(Intent intent) {
174 public int onStartCommand(Intent intent, int flags, int startId) {
178 @TargetApi(Build.VERSION_CODES.M)
180 public void onCreate() {
183 SharedPreferences pref = U.getSharedPreferences(this);
184 if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
185 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
188 pref.edit().putBoolean("taskbar_active", false).apply();
195 @SuppressLint("RtlHardcoded")
196 private void drawStartMenu() {
197 IconCache.getInstance(this).clearCache();
199 final SharedPreferences pref = U.getSharedPreferences(this);
200 final boolean hasHardwareKeyboard = getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
202 switch(pref.getString("show_search_bar", "keyboard")) {
204 shouldShowSearchBox = true;
207 shouldShowSearchBox = hasHardwareKeyboard;
210 shouldShowSearchBox = false;
214 // Initialize layout params
215 windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
216 U.setCachedRotation(windowManager.getDefaultDisplay().getRotation());
218 final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
219 WindowManager.LayoutParams.WRAP_CONTENT,
220 WindowManager.LayoutParams.WRAP_CONTENT,
221 CompatUtils.getOverlayType(),
222 shouldShowSearchBox ? 0 : WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
223 PixelFormat.TRANSLUCENT);
225 // Determine where to show the start menu on screen
226 switch(U.getTaskbarPosition(this)) {
228 layoutId = R.layout.start_menu_left;
229 params.gravity = Gravity.BOTTOM | Gravity.LEFT;
231 case "bottom_vertical_left":
232 layoutId = R.layout.start_menu_vertical_left;
233 params.gravity = Gravity.BOTTOM | Gravity.LEFT;
236 layoutId = R.layout.start_menu_right;
237 params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
239 case "bottom_vertical_right":
240 layoutId = R.layout.start_menu_vertical_right;
241 params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
244 layoutId = R.layout.start_menu_top_left;
245 params.gravity = Gravity.TOP | Gravity.LEFT;
247 case "top_vertical_left":
248 layoutId = R.layout.start_menu_vertical_left;
249 params.gravity = Gravity.TOP | Gravity.LEFT;
252 layoutId = R.layout.start_menu_top_right;
253 params.gravity = Gravity.TOP | Gravity.RIGHT;
255 case "top_vertical_right":
256 layoutId = R.layout.start_menu_vertical_right;
257 params.gravity = Gravity.TOP | Gravity.RIGHT;
264 switch(pref.getString("theme", "light")) {
266 theme = R.style.AppTheme;
269 theme = R.style.AppTheme_Dark;
273 ContextThemeWrapper wrapper = new ContextThemeWrapper(this, theme);
274 layout = (StartMenuLayout) LayoutInflater.from(wrapper).inflate(layoutId, null);
275 startMenu = U.findViewById(layout, R.id.start_menu);
277 if((shouldShowSearchBox && !hasHardwareKeyboard) || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1)
278 layout.viewHandlesBackButton();
280 boolean scrollbar = pref.getBoolean("scrollbar", false);
281 startMenu.setFastScrollEnabled(scrollbar);
282 startMenu.setFastScrollAlwaysVisible(scrollbar);
283 startMenu.setScrollBarStyle(scrollbar ? View.SCROLLBARS_OUTSIDE_INSET : View.SCROLLBARS_INSIDE_OVERLAY);
285 if(pref.getBoolean("transparent_start_menu", false))
286 startMenu.setBackgroundColor(0);
288 searchView = U.findViewById(layout, R.id.search);
290 int backgroundTint = U.getBackgroundTint(this);
292 FrameLayout startMenuFrame = U.findViewById(layout, R.id.start_menu_frame);
293 FrameLayout searchViewLayout = U.findViewById(layout, R.id.search_view_layout);
294 startMenuFrame.setBackgroundColor(backgroundTint);
295 searchViewLayout.setBackgroundColor(backgroundTint);
297 if(shouldShowSearchBox) {
298 if(!hasHardwareKeyboard) searchView.setIconifiedByDefault(true);
300 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
302 public boolean onQueryTextSubmit(String query) {
303 if(!hasSubmittedQuery) {
304 ListAdapter adapter = startMenu.getAdapter();
305 if(adapter != null) {
306 hasSubmittedQuery = true;
308 if(adapter.getCount() > 0) {
309 View view = adapter.getView(0, null, startMenu);
310 LinearLayout layout = U.findViewById(view, R.id.entry);
311 layout.performClick();
313 if(U.shouldCollapse(StartMenuService.this, true))
314 LocalBroadcastManager.getInstance(StartMenuService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_TASKBAR"));
316 LocalBroadcastManager.getInstance(StartMenuService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
320 if(Patterns.WEB_URL.matcher(query).matches()) {
321 intent = new Intent(Intent.ACTION_VIEW);
322 intent.setData(Uri.parse(URLUtil.guessUrl(query)));
323 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
325 intent = new Intent(Intent.ACTION_WEB_SEARCH);
326 intent.putExtra(SearchManager.QUERY, query);
327 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
330 if(intent.resolveActivity(getPackageManager()) != null)
331 startActivity(intent);
333 Uri uri = new Uri.Builder()
335 .authority("www.google.com")
337 .appendQueryParameter("q", query)
340 intent = new Intent(Intent.ACTION_VIEW);
342 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
345 startActivity(intent);
346 } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
355 public boolean onQueryTextChange(String newText) {
356 searchView.setIconified(false);
358 View closeButton = searchView.findViewById(R.id.search_close_btn);
359 if(closeButton != null) closeButton.setVisibility(View.GONE);
361 refreshApps(newText, false);
363 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
364 new Handler().postDelayed(() -> {
365 EditText editText = U.findViewById(searchView, R.id.search_src_text);
366 if(editText != null) {
367 editText.requestFocus();
368 editText.setSelection(editText.getText().length());
377 searchView.setOnQueryTextFocusChangeListener((view, b) -> {
378 if(!hasHardwareKeyboard) {
379 ViewGroup.LayoutParams params1 = startMenu.getLayoutParams();
380 params1.height = getResources().getDimensionPixelSize(
381 b && !isSecondScreenDisablingKeyboard()
382 ? R.dimen.start_menu_height_half
383 : R.dimen.start_menu_height);
384 startMenu.setLayoutParams(params1);
388 if(hasHardwareKeyboard && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1)
389 LocalBroadcastManager.getInstance(StartMenuService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
391 InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
392 imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
397 searchView.setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
399 LinearLayout powerButton = U.findViewById(layout, R.id.power_button);
400 powerButton.setOnClickListener(view -> {
401 int[] location = new int[2];
402 view.getLocationOnScreen(location);
403 openContextMenu(location);
406 powerButton.setOnGenericMotionListener((view, motionEvent) -> {
407 if(motionEvent.getAction() == MotionEvent.ACTION_BUTTON_PRESS
408 && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
409 int[] location = new int[2];
410 view.getLocationOnScreen(location);
411 openContextMenu(location);
416 searchViewLayout.setOnClickListener(view -> searchView.setIconified(false));
418 startMenu.setOnItemClickListener((parent, view, position, id) -> {
421 AppEntry entry = (AppEntry) parent.getAdapter().getItem(position);
422 U.launchApp(StartMenuService.this, entry.getPackageName(), entry.getComponentName(), entry.getUserId(StartMenuService.this), null, false, false);
425 if(pref.getBoolean("transparent_start_menu", false))
426 layout.findViewById(R.id.search_view_child_layout).setBackgroundColor(0);
428 searchViewLayout.setVisibility(View.GONE);
430 textView = U.findViewById(layout, R.id.no_apps_found);
432 LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
434 lbm.unregisterReceiver(toggleReceiver);
435 lbm.unregisterReceiver(hideReceiver);
436 lbm.unregisterReceiver(hideReceiverNoReset);
437 lbm.unregisterReceiver(showSpaceReceiver);
438 lbm.unregisterReceiver(hideSpaceReceiver);
439 lbm.unregisterReceiver(resetReceiver);
441 lbm.registerReceiver(toggleReceiver, new IntentFilter("com.farmerbb.taskbar.TOGGLE_START_MENU"));
442 lbm.registerReceiver(hideReceiver, new IntentFilter("com.farmerbb.taskbar.HIDE_START_MENU"));
443 lbm.registerReceiver(hideReceiverNoReset, new IntentFilter("com.farmerbb.taskbar.HIDE_START_MENU_NO_RESET"));
444 lbm.registerReceiver(showSpaceReceiver, new IntentFilter("com.farmerbb.taskbar.SHOW_START_MENU_SPACE"));
445 lbm.registerReceiver(hideSpaceReceiver, new IntentFilter("com.farmerbb.taskbar.HIDE_START_MENU_SPACE"));
446 lbm.registerReceiver(resetReceiver, new IntentFilter("com.farmerbb.taskbar.RESET_START_MENU"));
448 handler = new Handler();
451 windowManager.addView(layout, params);
454 private void refreshApps(boolean firstDraw) {
455 refreshApps(null, firstDraw);
458 private void refreshApps(final String query, final boolean firstDraw) {
459 if(thread != null) thread.interrupt();
461 handler = new Handler();
462 thread = new Thread(() -> {
463 if(pm == null) pm = getPackageManager();
465 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
466 LauncherApps launcherApps = (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
468 final List<UserHandle> userHandles = userManager.getUserProfiles();
469 final List<LauncherActivityInfo> unfilteredList = new ArrayList<>();
471 for(UserHandle handle : userHandles) {
472 unfilteredList.addAll(launcherApps.getActivityList(null, handle));
475 final List<LauncherActivityInfo> topAppsList = new ArrayList<>();
476 final List<LauncherActivityInfo> allAppsList = new ArrayList<>();
477 final List<LauncherActivityInfo> list = new ArrayList<>();
479 TopApps topApps = TopApps.getInstance(StartMenuService.this);
480 for(LauncherActivityInfo appInfo : unfilteredList) {
481 if(topApps.isTopApp(appInfo.getComponentName().flattenToString())
482 || topApps.isTopApp(appInfo.getName()))
483 topAppsList.add(appInfo);
486 Blacklist blacklist = Blacklist.getInstance(StartMenuService.this);
487 for(LauncherActivityInfo appInfo : unfilteredList) {
488 if(!(blacklist.isBlocked(appInfo.getComponentName().flattenToString())
489 || blacklist.isBlocked(appInfo.getName()))
490 && !(topApps.isTopApp(appInfo.getComponentName().flattenToString())
491 || topApps.isTopApp(appInfo.getName())))
492 allAppsList.add(appInfo);
495 Collections.sort(topAppsList, comparator);
496 Collections.sort(allAppsList, comparator);
498 list.addAll(topAppsList);
499 list.addAll(allAppsList);
504 List<LauncherActivityInfo> queryList;
508 queryList = new ArrayList<>();
509 for(LauncherActivityInfo appInfo : list) {
510 if(appInfo.getLabel().toString().toLowerCase().contains(query.toLowerCase()))
511 queryList.add(appInfo);
515 // Now that we've generated the list of apps,
516 // we need to determine if we need to redraw the start menu or not
517 boolean shouldRedrawStartMenu = false;
518 List<String> finalApplicationIds = new ArrayList<>();
520 if(query == null && !firstDraw) {
521 for(LauncherActivityInfo appInfo : queryList) {
522 finalApplicationIds.add(appInfo.getApplicationInfo().packageName);
525 if(finalApplicationIds.size() != currentStartMenuIds.size())
526 shouldRedrawStartMenu = true;
528 for(int i = 0; i < finalApplicationIds.size(); i++) {
529 if(!finalApplicationIds.get(i).equals(currentStartMenuIds.get(i))) {
530 shouldRedrawStartMenu = true;
535 } else shouldRedrawStartMenu = true;
537 if(shouldRedrawStartMenu) {
538 if(query == null) currentStartMenuIds = finalApplicationIds;
540 Drawable defaultIcon = pm.getDefaultActivityIcon();
542 final List<AppEntry> entries = new ArrayList<>();
543 for(LauncherActivityInfo appInfo : queryList) {
545 // Attempt to work around frequently reported OutOfMemoryErrors
550 label = appInfo.getLabel().toString();
551 icon = IconCache.getInstance(StartMenuService.this).getIcon(StartMenuService.this, pm, appInfo);
552 } catch (OutOfMemoryError e) {
555 label = appInfo.getApplicationInfo().packageName;
559 AppEntry newEntry = new AppEntry(
560 appInfo.getApplicationInfo().packageName,
562 appInfo.getApplicationInfo().packageName,
563 appInfo.getName()).flattenToString(),
568 newEntry.setUserId(userManager.getSerialNumberForUser(appInfo.getUser()));
569 entries.add(newEntry);
573 String queryText = searchView.getQuery().toString();
574 if(query == null && queryText.length() == 0
575 || query != null && query.equals(queryText)) {
576 StartMenuAdapter adapter;
577 SharedPreferences pref = U.getSharedPreferences(StartMenuService.this);
578 if(pref.getString("start_menu_layout", "list").equals("grid")) {
579 startMenu.setNumColumns(3);
580 adapter = new StartMenuAdapter(StartMenuService.this, R.layout.row_alt, entries);
582 adapter = new StartMenuAdapter(StartMenuService.this, R.layout.row, entries);
584 int position = startMenu.getFirstVisiblePosition();
585 startMenu.setAdapter(adapter);
586 startMenu.setSelection(position);
588 if(adapter.getCount() > 0)
589 textView.setText(null);
590 else if(query != null)
591 textView.setText(getString(Patterns.WEB_URL.matcher(query).matches() ? R.string.press_enter_alt : R.string.press_enter));
593 textView.setText(getString(R.string.nothing_to_see_here));
602 private void toggleStartMenu() {
603 if(layout.getVisibility() == View.GONE)
609 @SuppressWarnings("deprecation")
610 @TargetApi(Build.VERSION_CODES.N)
611 private void showStartMenu() {
612 if(layout.getVisibility() == View.GONE) {
613 layout.setOnClickListener(ocl);
614 layout.setVisibility(View.VISIBLE);
616 if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1)
619 MenuHelper.getInstance().setStartMenuOpen(true);
621 LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.farmerbb.taskbar.START_MENU_APPEARING"));
623 boolean onHomeScreen = LauncherHelper.getInstance().isOnHomeScreen();
624 boolean inFreeformMode = FreeformHackHelper.getInstance().isInFreeformWorkspace();
626 if(!U.isChromeOs(this) && (!onHomeScreen || inFreeformMode)) {
627 Class clazz = inFreeformMode && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
628 ? InvisibleActivityAlt.class
629 : InvisibleActivity.class;
631 Intent intent = new Intent(this, clazz);
632 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
633 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
636 if(clazz.equals(InvisibleActivity.class))
637 U.launchAppLowerRight(this, intent);
638 else if(clazz.equals(InvisibleActivityAlt.class))
639 U.launchAppMaximized(this, intent);
641 startActivity(intent);
644 if(searchView.getVisibility() == View.VISIBLE) searchView.requestFocus();
648 new Handler().postDelayed(() -> {
649 if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
652 InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
653 imm.hideSoftInputFromWindow(layout.getWindowToken(), 0);
658 private void hideStartMenu(boolean shouldReset) {
659 if(layout.getVisibility() == View.VISIBLE) {
660 layout.setOnClickListener(null);
663 MenuHelper.getInstance().setStartMenuOpen(false);
665 LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.farmerbb.taskbar.START_MENU_DISAPPEARING"));
667 layout.postDelayed(() -> {
668 layout.setVisibility(View.GONE);
669 searchView.setQuery(null, false);
670 searchView.setIconified(true);
671 hasSubmittedQuery = false;
674 startMenu.smoothScrollBy(0, 0);
675 startMenu.setSelection(0);
678 InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
679 imm.hideSoftInputFromWindow(layout.getWindowToken(), 0);
685 public void onDestroy() {
689 windowManager.removeView(layout);
690 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
692 LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
694 lbm.unregisterReceiver(toggleReceiver);
695 lbm.unregisterReceiver(hideReceiver);
696 lbm.unregisterReceiver(hideReceiverNoReset);
697 lbm.unregisterReceiver(showSpaceReceiver);
698 lbm.unregisterReceiver(hideSpaceReceiver);
699 lbm.unregisterReceiver(resetReceiver);
701 lbm.sendBroadcast(new Intent("com.farmerbb.taskbar.START_MENU_DISAPPEARING"));
704 @TargetApi(Build.VERSION_CODES.M)
706 public void onConfigurationChanged(Configuration newConfig) {
707 super.onConfigurationChanged(newConfig);
711 windowManager.removeView(layout);
712 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
714 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
717 SharedPreferences pref = U.getSharedPreferences(this);
718 pref.edit().putBoolean("taskbar_active", false).apply();
725 @SuppressWarnings("deprecation")
726 private void openContextMenu(final int[] location) {
727 LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU_NO_RESET"));
729 new Handler().postDelayed(() -> {
730 SharedPreferences pref = U.getSharedPreferences(StartMenuService.this);
731 Intent intent = null;
733 switch(pref.getString("theme", "light")) {
735 intent = new Intent(StartMenuService.this, ContextMenuActivity.class);
738 intent = new Intent(StartMenuService.this, ContextMenuActivityDark.class);
743 intent.putExtra("launched_from_start_menu", true);
744 intent.putExtra("is_overflow_menu", true);
745 intent.putExtra("x", location[0]);
746 intent.putExtra("y", location[1]);
747 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
750 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
751 DisplayMetrics metrics = U.getRealDisplayMetrics(this);
753 if(intent != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
754 intent.putExtra("context_menu_fix", true);
756 startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)).toBundle());
758 startActivity(intent);
759 }, shouldDelay() ? 100 : 0);
762 private boolean shouldDelay() {
763 SharedPreferences pref = U.getSharedPreferences(this);
764 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
765 && pref.getBoolean("freeform_hack", false)
766 && !FreeformHackHelper.getInstance().isFreeformHackActive();
769 private boolean isSecondScreenDisablingKeyboard() {
770 return Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD)
771 .startsWith("com.farmerbb.secondscreen");