package de.theknut.xposedgelsettings.hooks.googlesearchbar; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; import de.theknut.xposedgelsettings.R; import de.theknut.xposedgelsettings.hooks.Common; import de.theknut.xposedgelsettings.hooks.HooksBaseClass; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper.Classes; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper.Fields; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper.Methods; import de.theknut.xposedgelsettings.hooks.PreferencesHelper; import de.theknut.xposedgelsettings.hooks.Utils; import de.theknut.xposedgelsettings.hooks.common.CommonHooks; import de.theknut.xposedgelsettings.hooks.googlesearchbar.weatherwidget.WeatherWidget; import static de.robv.android.xposed.XposedHelpers.callMethod; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import static de.robv.android.xposed.XposedHelpers.getIntField; import static de.robv.android.xposed.XposedHelpers.getObjectField; import static de.robv.android.xposed.XposedHelpers.setObjectField; public class GoogleSearchBarHooks extends HooksBaseClass { public static void initAllHooks(final LoadPackageParam lpparam) { if (PreferencesHelper.hideSearchBar) { // hide Google Search Bar CommonHooks.GetWorkspacePaddingListeners.add(new GetWorkspacePaddingHook()); findAndHookMethod(Classes.Launcher, "onCreate", Bundle.class, new LauncherOnCreateHook()); if (PreferencesHelper.searchBarOnDefaultHomescreen) { // show on default homescreen CommonHooks.LauncherOnResumeListeners.add(new LauncherOnResumeHook()); // hide search bar when the page is beeing moved CommonHooks.PageBeginMovingListeners.add(new OnPageBeginMovingHook()); // show search bar if GNow is visible CommonHooks.PageEndMovingListeners.add(new OnPageEndMovingHook()); if (Common.HOOKED_PACKAGE.equals(Common.GEL_PACKAGE)) { blockSearchbarTransitions(lpparam); } } // only do the following changes if we have the actual GEL launcher with GNow if (Common.HOOKED_PACKAGE.equals(Common.GEL_PACKAGE)) { // hide search bar when the page is beeing moved CommonHooks.PageBeginMovingListeners.add(new OnPageBeginMovingHook()); if (PreferencesHelper.autoHideSearchBar) { // show search bar if GNow is visible CommonHooks.PageEndMovingListeners.add(new OnPageEndMovingHook()); // show Google Search Bar on GEL sidekick - needed if GNow isn't accessed from the homescreen CommonHooks.OnNowShowListeners.add(new OnShowNowOverlayHook()); blockSearchbarTransitions(lpparam); } // show when doing a Google search findAndHookMethod(Classes.SearchOverlayImpl, Methods.soiSetSearchStarted, boolean.class, new SetSearchStarted()); } // show DropDeleteTarget on dragging items CommonHooks.OnDragStartListeners.add(new OnDragStart()); CommonHooks.OnDragEndListeners.add(new OnDragEnd()); } if (Common.HOOKED_PACKAGE.equals(Common.GEL_PACKAGE)) { final int color = Color.WHITE; final int darkerColor = 0xFFF4F4F4; if (Common.GNL_VERSION >= ObfuscationHelper.GNL_4_2_16) { if (Common.GNL_VERSION < ObfuscationHelper.GNL_5_2_33 || Common.GNL_VERSION >= ObfuscationHelper.GNL_5_3_23) { findAndHookMethod(Classes.SearchSettings, Methods.ssFirstHotwordHintShownAt, XC_MethodReplacement.returnConstant(PreferencesHelper.alwaysShowSayOKGoogle)); findAndHookMethod(Classes.HintTextView, Methods.htvAnimateHotword, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { ((View) param.thisObject).setAlpha(0.0F); param.setResult(null); } }); } XposedBridge.hookAllConstructors(Classes.SearchPlateBar, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Drawable searchBg = (Drawable) getObjectField(param.thisObject, Fields.spbMic); searchBg.setColorFilter(PreferencesHelper.searchbarPrimaryColor, PorterDuff.Mode.MULTIPLY); } }); findAndHookMethod(Classes.SearchPlate, "onFinishInflate", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { ViewGroup searchPlate = (ViewGroup) param.thisObject; Resources resources = searchPlate.getContext().getResources(); Drawable dMic = null, dLogo = null; ImageView logo = (ImageView) searchPlate.findViewById(resources.getIdentifier("launcher_search_button", "id", Common.HOOKED_PACKAGE)); ImageView mic = (ImageView) searchPlate.findViewById(resources.getIdentifier("clear_or_voice_button", "id", Common.HOOKED_PACKAGE)); switch (PreferencesHelper.searchbarStyle) { case 0: return; case 1: boolean useWhite = Utils.getContrastColor(PreferencesHelper.searchbarPrimaryColor) == Color.WHITE; dLogo = Common.XGELS_CONTEXT.getResources().getDrawable(useWhite ? R.drawable.ic_google_small_light : R.drawable.ic_searchbox_google); dMic = Common.XGELS_CONTEXT.getResources().getDrawable(useWhite ? R.drawable.ic_mic_m_white : R.drawable.ic_mic_dark); break; case 2: dLogo = Common.XGELS_CONTEXT.getResources().getDrawable(R.drawable.ic_searchbox_google_m); dMic = Common.XGELS_CONTEXT.getResources().getDrawable(R.drawable.ic_mic_m); break; case 3: dLogo = Common.XGELS_CONTEXT.getResources().getDrawable(R.drawable.ic_searchbox_google_m_monochrome); dMic = Common.XGELS_CONTEXT.getResources().getDrawable(R.drawable.ic_mic_m_monochrome); break; } logo.setImageDrawable(dLogo); setObjectField(mic, Fields.covbFields[2], dMic); setObjectField(mic, Fields.covbFields[3], dMic); } }); if (PreferencesHelper.searchbarStyle != 3 && Utils.getContrastColor(PreferencesHelper.searchbarPrimaryColor) == Color.WHITE) { findAndHookMethod(Classes.SearchPlate, "onFinishInflate", new XC_MethodHook(PRIORITY_HIGHEST) { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { ViewGroup searchPlate = (ViewGroup) param.thisObject; Resources resources = searchPlate.getContext().getResources(); int id = resources.getIdentifier("search_box", "id", Common.HOOKED_PACKAGE); if (id != 0) { EditText simpleSearchText = (EditText) searchPlate.findViewById(id); simpleSearchText.setTextColor(color); simpleSearchText.setHintTextColor(darkerColor); } id = resources.getIdentifier("say_ok_google", "id", Common.HOOKED_PACKAGE); if (id != 0) { ((TextView) searchPlate.findViewById(id)).setTextColor(darkerColor); } if (Common.GNL_VERSION < ObfuscationHelper.GNL_5_3_23) { id = resources.getIdentifier("clear_or_voice_butpeton", "id", Common.HOOKED_PACKAGE); if (id != 0) { View clearOrVoiceButton = searchPlate.findViewById(id); if (Common.GNL_VERSION >= ObfuscationHelper.GNL_4_7_12 || Common.GNL_VERSION == ObfuscationHelper.GNL_4_7_13) { callMethod(clearOrVoiceButton, Methods.covbMethods[0]); callMethod(clearOrVoiceButton, Methods.covbMethods[1]); callMethod(clearOrVoiceButton, Methods.covbMethods[2]); } Paint paint = (Paint) getObjectField(clearOrVoiceButton, Fields.covbFields[0]); if (paint != null) paint.setColor(darkerColor); ((Drawable) getObjectField(clearOrVoiceButton, Fields.covbFields[1])).setColorFilter(color, PorterDuff.Mode.MULTIPLY); ((Drawable) getObjectField(clearOrVoiceButton, Fields.covbFields[2])).setColorFilter(color, PorterDuff.Mode.MULTIPLY); ((Drawable) getObjectField(clearOrVoiceButton, Fields.covbFields[3])).setColorFilter(color, PorterDuff.Mode.MULTIPLY); } } } }); } } // 0 - Default // 1 - Android L if (PreferencesHelper.searchbarStyle == 1 && Common.IS_PRE_GNL_4) { XC_MethodHook proximityToNowHook = new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (PreferencesHelper.searchbarStyle == 1) { param.args[0] = 1f; } } }; findAndHookMethod(Classes.SearchPlate, Methods.spSetProximityToNow, float.class, proximityToNowHook); findAndHookMethod(Classes.GelSearchPlateContainer, Methods.spSetProximityToNow, float.class, proximityToNowHook); } if (Common.GNL_VERSION > ObfuscationHelper.GNL_4_0_26) { WeatherWidget.initAllHooks(lpparam); } } } private static void blockSearchbarTransitions(LoadPackageParam lpparam) { if (Common.GNL_VERSION >= ObfuscationHelper.GNL_5_3_23) { // avoid that nasty animation when showing the search bar again findAndHookMethod(Classes.TransitionsManager, Methods.tmSetTransitionsEnabled, boolean.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = false; } }); if (Common.GNL_VERSION < ObfuscationHelper.GNL_5_10_22) { findAndHookMethod(Classes.HintTextView, Methods.htvAnimateHotword, boolean.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { int page = getIntField(Common.WORKSPACE_INSTANCE, Fields.pvCurrentPage); boolean shouldShow = (page == 0 && PreferencesHelper.autoHideSearchBar) || (PreferencesHelper.searchBarOnDefaultHomescreen && page == (PreferencesHelper.defaultHomescreen - 1)); // show the search bar as soon as the page has stopped moving and the GNow overlay is visible if ((Common.IS_KK_TREBUCHET || (Boolean) callMethod(Common.LAUNCHER_INSTANCE, Methods.lHasCustomContentToLeft)) && shouldShow) { param.args[0] = false; } } }); } } else { // avoid that nasty animation when showing the search bar again findAndHookMethod(Classes.TransitionsManager, Methods.tmSetTransitionsEnabled, boolean.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = false; } }); } } // method to hide the Google search bar public static void hideSearchbar() { setLayoutParams(false); } // method to show the Google search bar public static void showSearchbar() { setLayoutParams(true); } // method to show or hide the Google search bar public static void setLayoutParams(final boolean show) { if (Common.LAUNCHER_INSTANCE == null) { log("Couldn't do anything because the launcher instance is null"); return; } // Layout the search bar space View searchBar = (View) getObjectField(Common.LAUNCHER_INSTANCE, Fields.lSearchDropTargetBar); final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); if (Common.SEARCH_BAR_SPACE_HEIGHT == -1 && lp.height != 0) { Common.SEARCH_BAR_SPACE_HEIGHT = lp.height; } lp.height = show ? Common.SEARCH_BAR_SPACE_HEIGHT : 0; // Layout the search bar View qsbBar; if (Common.PACKAGE_OBFUSCATED && Common.GNL_VERSION >= ObfuscationHelper.GNL_4_1_21) { qsbBar = (View) getObjectField(searchBar, Fields.sdtbQsbBar); } else { qsbBar = (View) callMethod(Common.LAUNCHER_INSTANCE, Methods.lGetQsbBar); } LayoutParams vglp = qsbBar.getLayoutParams(); vglp.width = show ? LayoutParams.MATCH_PARENT : 0; vglp.height = show ? LayoutParams.MATCH_PARENT : 0; qsbBar.setLayoutParams(vglp); } }