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.ui;
18 import android.annotation.SuppressLint;
19 import android.annotation.TargetApi;
20 import android.app.SearchManager;
21 import android.content.ActivityNotFoundException;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.content.pm.LauncherActivityInfo;
28 import android.content.pm.LauncherApps;
29 import android.content.pm.PackageManager;
30 import android.content.res.Configuration;
31 import android.graphics.drawable.Drawable;
32 import android.net.Uri;
33 import android.os.Build;
34 import android.os.Bundle;
35 import android.os.Handler;
36 import android.os.UserHandle;
37 import android.os.UserManager;
38 import android.provider.Settings;
39 import androidx.appcompat.widget.SearchView;
40 import android.util.Patterns;
41 import android.view.Gravity;
42 import android.view.LayoutInflater;
43 import android.view.MotionEvent;
44 import android.view.View;
45 import android.view.ViewGroup;
46 import android.view.WindowManager;
47 import android.view.inputmethod.EditorInfo;
48 import android.view.inputmethod.InputMethodManager;
49 import android.webkit.URLUtil;
50 import android.widget.EditText;
51 import android.widget.FrameLayout;
52 import android.widget.GridView;
53 import android.widget.LinearLayout;
54 import android.widget.ListAdapter;
55 import android.widget.TextView;
57 import com.farmerbb.taskbar.R;
58 import com.farmerbb.taskbar.activity.InvisibleActivity;
59 import com.farmerbb.taskbar.activity.InvisibleActivityAlt;
60 import com.farmerbb.taskbar.adapter.StartMenuAdapter;
61 import com.farmerbb.taskbar.content.TaskbarIntent;
62 import com.farmerbb.taskbar.util.AppEntry;
63 import com.farmerbb.taskbar.util.Blacklist;
64 import com.farmerbb.taskbar.util.FreeformHackHelper;
65 import com.farmerbb.taskbar.util.IconCache;
66 import com.farmerbb.taskbar.util.LauncherHelper;
67 import com.farmerbb.taskbar.util.MenuHelper;
68 import com.farmerbb.taskbar.util.TopApps;
69 import com.farmerbb.taskbar.util.U;
70 import com.farmerbb.taskbar.widget.StartMenuLayout;
72 import java.text.Collator;
73 import java.util.ArrayList;
74 import java.util.Collections;
75 import java.util.Comparator;
76 import java.util.List;
78 public class StartMenuController implements UIController {
80 private Context context;
81 private StartMenuLayout layout;
82 private GridView startMenu;
83 private SearchView searchView;
84 private TextView textView;
85 private PackageManager pm;
86 private StartMenuAdapter adapter;
88 private Handler handler;
89 private Thread thread;
91 private boolean shouldShowSearchBox = false;
92 private boolean hasSubmittedQuery = false;
93 private boolean hasHardwareKeyboard = false;
94 private boolean searchViewClicked = false;
96 private int layoutId = R.layout.tb_start_menu_left;
98 private List<String> currentStartMenuIds = new ArrayList<>();
100 private View.OnClickListener ocl = view -> toggleStartMenu();
102 private BroadcastReceiver toggleReceiver = new BroadcastReceiver() {
104 public void onReceive(Context context, Intent intent) {
109 private BroadcastReceiver showSpaceReceiver = new BroadcastReceiver() {
111 public void onReceive(Context context, Intent intent) {
112 layout.findViewById(R.id.start_menu_space).setVisibility(View.VISIBLE);
116 private BroadcastReceiver hideSpaceReceiver = new BroadcastReceiver() {
118 public void onReceive(Context context, Intent intent) {
119 layout.findViewById(R.id.start_menu_space).setVisibility(View.GONE);
123 private BroadcastReceiver hideReceiver = new BroadcastReceiver() {
125 public void onReceive(Context context, Intent intent) {
130 private BroadcastReceiver hideReceiverNoReset = new BroadcastReceiver() {
132 public void onReceive(Context context, Intent intent) {
133 hideStartMenu(false);
137 private BroadcastReceiver resetReceiver = new BroadcastReceiver() {
139 public void onReceive(Context context, Intent intent) {
140 startMenu.setSelection(0);
144 private Comparator<LauncherActivityInfo> comparator = (ai1, ai2) -> {
149 label1 = ai1.getLabel().toString();
150 label2 = ai2.getLabel().toString();
151 } catch (OutOfMemoryError e) {
154 label1 = ai1.getApplicationInfo().packageName;
155 label2 = ai2.getApplicationInfo().packageName;
158 return Collator.getInstance().compare(label1, label2);
161 public StartMenuController(Context context) {
162 this.context = context;
165 @TargetApi(Build.VERSION_CODES.M)
167 public void onCreateHost(UIHost host) {
168 hasHardwareKeyboard = context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
170 SharedPreferences pref = U.getSharedPreferences(context);
171 if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
172 if(U.canDrawOverlays(context))
175 pref.edit().putBoolean("taskbar_active", false).apply();
179 } else host.terminate();
182 @SuppressLint("RtlHardcoded")
183 private void drawStartMenu(UIHost host) {
184 IconCache.getInstance(context).clearCache();
186 final SharedPreferences pref = U.getSharedPreferences(context);
187 switch(pref.getString("show_search_bar", "always")) {
189 shouldShowSearchBox = true;
192 shouldShowSearchBox = hasHardwareKeyboard;
195 shouldShowSearchBox = false;
199 // Initialize layout params
200 WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
201 U.setCachedRotation(windowManager.getDefaultDisplay().getRotation());
203 final ViewParams params = new ViewParams(
204 WindowManager.LayoutParams.WRAP_CONTENT,
205 WindowManager.LayoutParams.WRAP_CONTENT,
207 shouldShowSearchBox ? 0 : WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
210 // Determine where to show the start menu on screen
211 switch(U.getTaskbarPosition(context)) {
213 layoutId = R.layout.tb_start_menu_left;
214 params.gravity = Gravity.BOTTOM | Gravity.LEFT;
216 case "bottom_vertical_left":
217 layoutId = R.layout.tb_start_menu_vertical_left;
218 params.gravity = Gravity.BOTTOM | Gravity.LEFT;
221 layoutId = R.layout.tb_start_menu_right;
222 params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
224 case "bottom_vertical_right":
225 layoutId = R.layout.tb_start_menu_vertical_right;
226 params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
229 layoutId = R.layout.tb_start_menu_top_left;
230 params.gravity = Gravity.TOP | Gravity.LEFT;
232 case "top_vertical_left":
233 layoutId = R.layout.tb_start_menu_vertical_left;
234 params.gravity = Gravity.TOP | Gravity.LEFT;
237 layoutId = R.layout.tb_start_menu_top_right;
238 params.gravity = Gravity.TOP | Gravity.RIGHT;
240 case "top_vertical_right":
241 layoutId = R.layout.tb_start_menu_vertical_right;
242 params.gravity = Gravity.TOP | Gravity.RIGHT;
247 layout = (StartMenuLayout) LayoutInflater.from(U.wrapContext(context)).inflate(layoutId, null);
250 startMenu = layout.findViewById(R.id.start_menu);
252 if((shouldShowSearchBox && !hasHardwareKeyboard) || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1)
253 layout.viewHandlesBackButton();
255 boolean scrollbar = pref.getBoolean("scrollbar", false);
256 startMenu.setFastScrollEnabled(scrollbar);
257 startMenu.setFastScrollAlwaysVisible(scrollbar);
258 startMenu.setScrollBarStyle(scrollbar ? View.SCROLLBARS_OUTSIDE_INSET : View.SCROLLBARS_INSIDE_OVERLAY);
260 if(pref.getBoolean("transparent_start_menu", false))
261 startMenu.setBackgroundColor(0);
263 if(pref.getBoolean("visual_feedback", true))
264 startMenu.setRecyclerListener(view -> view.setBackgroundColor(0));
266 int columns = context.getResources().getInteger(R.integer.tb_start_menu_columns);
267 boolean isGrid = pref.getString("start_menu_layout", "grid").equals("grid");
270 ViewGroup.LayoutParams startMenuParams = startMenu.getLayoutParams();
271 startMenuParams.width = (int) (startMenuParams.width * (columns / 3f));
272 startMenu.setLayoutParams(startMenuParams);
275 searchView = layout.findViewById(R.id.search);
276 searchViewClicked = false;
278 int backgroundTint = U.getBackgroundTint(context);
280 FrameLayout startMenuFrame = layout.findViewById(R.id.start_menu_frame);
281 FrameLayout searchViewLayout = layout.findViewById(R.id.search_view_layout);
282 startMenuFrame.setBackgroundColor(backgroundTint);
283 searchViewLayout.setBackgroundColor(backgroundTint);
285 if(shouldShowSearchBox) {
286 if(!hasHardwareKeyboard) searchView.setIconifiedByDefault(true);
288 searchView.setOnTouchListener((v, event) -> {
289 searchViewClicked = true;
293 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
295 public boolean onQueryTextSubmit(String query) {
296 if(!hasSubmittedQuery) {
297 ListAdapter adapter = startMenu.getAdapter();
298 if(adapter != null) {
299 hasSubmittedQuery = true;
301 if(adapter.getCount() > 0) {
302 View view = adapter.getView(0, null, startMenu);
303 LinearLayout layout = view.findViewById(R.id.entry);
304 layout.performClick();
306 if(U.shouldCollapse(context, true)) {
307 U.sendBroadcast(context, TaskbarIntent.ACTION_HIDE_TASKBAR);
309 U.sendBroadcast(context, TaskbarIntent.ACTION_HIDE_START_MENU);
314 if(Patterns.WEB_URL.matcher(query).matches()) {
315 intent = new Intent(Intent.ACTION_VIEW);
316 intent.setData(Uri.parse(URLUtil.guessUrl(query)));
318 intent = new Intent(Intent.ACTION_WEB_SEARCH);
319 intent.putExtra(SearchManager.QUERY, query);
322 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
324 if(intent.resolveActivity(context.getPackageManager()) != null)
325 context.startActivity(intent);
327 Uri uri = new Uri.Builder()
329 .authority("www.google.com")
331 .appendQueryParameter("q", query)
334 intent = new Intent(Intent.ACTION_VIEW);
336 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
339 context.startActivity(intent);
340 } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
349 public boolean onQueryTextChange(String newText) {
350 searchView.setIconified(false);
352 View closeButton = searchView.findViewById(R.id.search_close_btn);
353 if(closeButton != null) closeButton.setVisibility(View.GONE);
355 refreshApps(newText, false);
357 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
358 new Handler().postDelayed(() -> {
359 EditText editText = searchView.findViewById(R.id.search_src_text);
360 if(editText != null) {
361 editText.requestFocus();
362 editText.setSelection(editText.getText().length());
371 searchView.setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
373 LinearLayout powerButton = layout.findViewById(R.id.power_button);
374 powerButton.setOnClickListener(view -> {
375 int[] location = new int[2];
376 view.getLocationOnScreen(location);
377 openContextMenu(location);
380 powerButton.setOnGenericMotionListener((view, motionEvent) -> {
381 if(motionEvent.getAction() == MotionEvent.ACTION_BUTTON_PRESS
382 && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
383 int[] location = new int[2];
384 view.getLocationOnScreen(location);
385 openContextMenu(location);
390 searchViewLayout.setOnClickListener(view -> searchView.setIconified(false));
392 startMenu.setOnItemClickListener((viewParent, view, position, id) -> {
395 AppEntry entry = (AppEntry) viewParent.getAdapter().getItem(position);
396 U.launchApp(context, entry, null, false, false, view);
399 View childLayout = layout.findViewById(R.id.search_view_child_layout);
400 if(pref.getBoolean("transparent_start_menu", false))
401 childLayout.setBackgroundColor(0);
404 ViewGroup.LayoutParams childLayoutParams = childLayout.getLayoutParams();
405 childLayoutParams.width = (int) (childLayoutParams.width * (columns / 3f));
406 childLayout.setLayoutParams(childLayoutParams);
409 searchViewLayout.setVisibility(View.GONE);
411 textView = layout.findViewById(R.id.no_apps_found);
413 U.unregisterReceiver(context, toggleReceiver);
414 U.unregisterReceiver(context, hideReceiver);
415 U.unregisterReceiver(context, hideReceiverNoReset);
416 U.unregisterReceiver(context, showSpaceReceiver);
417 U.unregisterReceiver(context, hideSpaceReceiver);
418 U.unregisterReceiver(context, resetReceiver);
420 U.registerReceiver(context, toggleReceiver, TaskbarIntent.ACTION_TOGGLE_START_MENU);
421 U.registerReceiver(context, hideReceiver, TaskbarIntent.ACTION_HIDE_START_MENU);
422 U.registerReceiver(context, hideReceiverNoReset, TaskbarIntent.ACTION_HIDE_START_MENU_NO_RESET);
423 U.registerReceiver(context, showSpaceReceiver, TaskbarIntent.ACTION_SHOW_START_MENU_SPACE);
424 U.registerReceiver(context, hideSpaceReceiver, TaskbarIntent.ACTION_HIDE_START_MENU_SPACE);
425 U.registerReceiver(context, resetReceiver, TaskbarIntent.ACTION_RESET_START_MENU);
427 handler = new Handler();
430 host.addView(layout, params);
433 private void refreshApps(boolean firstDraw) {
434 refreshApps(null, firstDraw);
437 private void refreshApps(final String query, final boolean firstDraw) {
438 if(thread != null) thread.interrupt();
440 handler = new Handler();
441 thread = new Thread(() -> {
442 if(pm == null) pm = context.getPackageManager();
444 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
445 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
447 final List<UserHandle> userHandles = userManager.getUserProfiles();
448 final List<LauncherActivityInfo> unfilteredList = new ArrayList<>();
450 for(UserHandle handle : userHandles) {
451 unfilteredList.addAll(launcherApps.getActivityList(null, handle));
454 final List<LauncherActivityInfo> topAppsList = new ArrayList<>();
455 final List<LauncherActivityInfo> allAppsList = new ArrayList<>();
456 final List<LauncherActivityInfo> list = new ArrayList<>();
458 TopApps topApps = TopApps.getInstance(context);
459 for(LauncherActivityInfo appInfo : unfilteredList) {
460 String userSuffix = ":" + userManager.getSerialNumberForUser(appInfo.getUser());
461 if(topApps.isTopApp(appInfo.getComponentName().flattenToString() + userSuffix)
462 || topApps.isTopApp(appInfo.getComponentName().flattenToString())
463 || topApps.isTopApp(appInfo.getName()))
464 topAppsList.add(appInfo);
467 Blacklist blacklist = Blacklist.getInstance(context);
468 for(LauncherActivityInfo appInfo : unfilteredList) {
469 String userSuffix = ":" + userManager.getSerialNumberForUser(appInfo.getUser());
470 if(!(blacklist.isBlocked(appInfo.getComponentName().flattenToString() + userSuffix)
471 || blacklist.isBlocked(appInfo.getComponentName().flattenToString())
472 || blacklist.isBlocked(appInfo.getName()))
473 && !(topApps.isTopApp(appInfo.getComponentName().flattenToString() + userSuffix)
474 || topApps.isTopApp(appInfo.getComponentName().flattenToString())
475 || topApps.isTopApp(appInfo.getName())))
476 allAppsList.add(appInfo);
479 Collections.sort(topAppsList, comparator);
480 Collections.sort(allAppsList, comparator);
482 list.addAll(topAppsList);
483 list.addAll(allAppsList);
488 List<LauncherActivityInfo> queryList;
492 queryList = new ArrayList<>();
493 for(LauncherActivityInfo appInfo : list) {
494 if(appInfo.getLabel().toString().toLowerCase().contains(query.toLowerCase()))
495 queryList.add(appInfo);
499 // Now that we've generated the list of apps,
500 // we need to determine if we need to redraw the start menu or not
501 boolean shouldRedrawStartMenu = false;
502 List<String> finalApplicationIds = new ArrayList<>();
504 if(query == null && !firstDraw) {
505 for(LauncherActivityInfo appInfo : queryList) {
506 finalApplicationIds.add(appInfo.getApplicationInfo().packageName);
509 if(finalApplicationIds.size() != currentStartMenuIds.size())
510 shouldRedrawStartMenu = true;
512 for(int i = 0; i < finalApplicationIds.size(); i++) {
513 if(!finalApplicationIds.get(i).equals(currentStartMenuIds.get(i))) {
514 shouldRedrawStartMenu = true;
519 } else shouldRedrawStartMenu = true;
521 if(shouldRedrawStartMenu) {
522 if(query == null) currentStartMenuIds = finalApplicationIds;
524 Drawable defaultIcon = pm.getDefaultActivityIcon();
526 final List<AppEntry> entries = new ArrayList<>();
527 for(LauncherActivityInfo appInfo : queryList) {
529 // Attempt to work around frequently reported OutOfMemoryErrors
534 label = appInfo.getLabel().toString();
535 icon = IconCache.getInstance(context).getIcon(context, pm, appInfo);
536 } catch (OutOfMemoryError e) {
539 label = appInfo.getApplicationInfo().packageName;
543 AppEntry newEntry = new AppEntry(
544 appInfo.getApplicationInfo().packageName,
546 appInfo.getApplicationInfo().packageName,
547 appInfo.getName()).flattenToString(),
552 newEntry.setUserId(userManager.getSerialNumberForUser(appInfo.getUser()));
553 entries.add(newEntry);
557 String queryText = searchView.getQuery().toString();
558 if(query == null && queryText.length() == 0
559 || query != null && query.equals(queryText)) {
562 SharedPreferences pref = U.getSharedPreferences(context);
563 if(pref.getString("start_menu_layout", "grid").equals("grid")) {
564 startMenu.setNumColumns(context.getResources().getInteger(R.integer.tb_start_menu_columns));
565 adapter = new StartMenuAdapter(context, R.layout.tb_row_alt, entries);
567 adapter = new StartMenuAdapter(context, R.layout.tb_row, entries);
569 startMenu.setAdapter(adapter);
572 int position = startMenu.getFirstVisiblePosition();
574 if(!firstDraw && adapter != null)
575 adapter.updateList(entries);
577 startMenu.setSelection(position);
579 if(adapter != null && adapter.getCount() > 0)
580 textView.setText(null);
581 else if(query != null)
582 textView.setText(context.getString(Patterns.WEB_URL.matcher(query).matches() ? R.string.tb_press_enter_alt : R.string.tb_press_enter));
584 textView.setText(context.getString(R.string.tb_nothing_to_see_here));
593 private void toggleStartMenu() {
594 if(layout.getVisibility() == View.GONE)
600 @TargetApi(Build.VERSION_CODES.N)
601 private void showStartMenu() {
602 if(layout.getVisibility() == View.GONE) {
603 layout.setOnClickListener(ocl);
604 layout.setVisibility(View.VISIBLE);
606 if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && !hasHardwareKeyboard)
609 MenuHelper.getInstance().setStartMenuOpen(true);
611 U.sendBroadcast(context, TaskbarIntent.ACTION_START_MENU_APPEARING);
613 boolean onHomeScreen = LauncherHelper.getInstance().isOnHomeScreen();
614 boolean inFreeformMode = FreeformHackHelper.getInstance().isInFreeformWorkspace();
616 if(!U.isChromeOs(context) && (!onHomeScreen || inFreeformMode)) {
617 Class clazz = inFreeformMode && !U.hasBrokenSetLaunchBoundsApi()
618 ? InvisibleActivityAlt.class
619 : InvisibleActivity.class;
621 Intent intent = new Intent(context, clazz);
622 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
623 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
626 if(clazz.equals(InvisibleActivity.class))
627 U.startActivityLowerRight(context, intent);
628 else if(clazz.equals(InvisibleActivityAlt.class))
629 U.startActivityMaximized(context, intent);
631 context.startActivity(intent);
634 EditText editText = searchView.findViewById(R.id.search_src_text);
635 if(searchView.getVisibility() == View.VISIBLE) {
636 if(hasHardwareKeyboard) {
637 searchView.setIconifiedByDefault(true);
640 editText.setShowSoftInputOnFocus(false);
642 searchView.requestFocus();
647 new Handler().postDelayed(() -> {
648 if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1 || hasHardwareKeyboard)
651 if(hasHardwareKeyboard) {
652 searchView.setIconifiedByDefault(false);
654 editText.setShowSoftInputOnFocus(true);
656 searchView.requestFocus();
659 searchView.setOnQueryTextFocusChangeListener((view, b) -> {
660 if(!hasHardwareKeyboard) {
661 ViewGroup.LayoutParams params1 = startMenu.getLayoutParams();
662 params1.height = context.getResources().getDimensionPixelSize(
663 b && !isSecondScreenDisablingKeyboard()
664 ? R.dimen.tb_start_menu_height_half
665 : R.dimen.tb_start_menu_height);
666 startMenu.setLayoutParams(params1);
670 if(hasHardwareKeyboard && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
671 U.sendBroadcast(context, TaskbarIntent.ACTION_HIDE_START_MENU);
673 InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
674 imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
679 InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
680 imm.hideSoftInputFromWindow(layout.getWindowToken(), 0);
685 private void hideStartMenu(boolean shouldReset) {
686 if(layout.getVisibility() == View.VISIBLE) {
687 layout.setOnClickListener(null);
690 MenuHelper.getInstance().setStartMenuOpen(false);
692 U.sendBroadcast(context, TaskbarIntent.ACTION_START_MENU_DISAPPEARING);
694 layout.postDelayed(() -> {
695 layout.setVisibility(View.GONE);
697 if(searchViewClicked || hasHardwareKeyboard) {
698 if(!hasHardwareKeyboard)
699 searchView.setQuery(null, false);
701 searchView.setIconified(true);
704 searchView.setOnQueryTextFocusChangeListener(null);
705 hasSubmittedQuery = false;
708 startMenu.smoothScrollBy(0, 0);
709 startMenu.setSelection(0);
712 InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
713 imm.hideSoftInputFromWindow(layout.getWindowToken(), 0);
719 public void onDestroyHost(UIHost host) {
722 host.removeView(layout);
723 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
725 U.unregisterReceiver(context, toggleReceiver);
726 U.unregisterReceiver(context, hideReceiver);
727 U.unregisterReceiver(context, hideReceiverNoReset);
728 U.unregisterReceiver(context, showSpaceReceiver);
729 U.unregisterReceiver(context, hideSpaceReceiver);
730 U.unregisterReceiver(context, resetReceiver);
732 U.sendBroadcast(context, TaskbarIntent.ACTION_START_MENU_DISAPPEARING);
735 @TargetApi(Build.VERSION_CODES.M)
737 public void onRecreateHost(UIHost host) {
740 host.removeView(layout);
741 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
743 if(U.canDrawOverlays(context))
746 SharedPreferences pref = U.getSharedPreferences(context);
747 pref.edit().putBoolean("taskbar_active", false).apply();
754 private void openContextMenu(final int[] location) {
755 U.sendBroadcast(context, TaskbarIntent.ACTION_HIDE_START_MENU_NO_RESET);
757 Bundle args = new Bundle();
758 args.putBoolean("launched_from_start_menu", true);
759 args.putBoolean("is_overflow_menu", true);
760 args.putInt("x", location[0]);
761 args.putInt("y", location[1]);
763 new Handler().postDelayed(() -> U.startContextMenuActivity(context, args), shouldDelay() ? 100 : 0);
766 private boolean shouldDelay() {
767 SharedPreferences pref = U.getSharedPreferences(context);
768 return U.hasFreeformSupport(context)
769 && pref.getBoolean("freeform_hack", false)
770 && !FreeformHackHelper.getInstance().isFreeformHackActive();
773 private boolean isSecondScreenDisablingKeyboard() {
774 return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD)
775 .startsWith("com.farmerbb.secondscreen");