Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1b7dbb8 authored by Sven Dawitz's avatar Sven Dawitz
Browse files

CM Tablet tweaks project (Ready for merge)

Since tablets handle various things differently than phones, it requires
some modifications on the framework. After a lot of discussion, i came
up with this todo list: http://kan.gd/3vb

Included features (in chronological order):
- Toggle status bar top/bottom via cm settings. Changes position on the
  fly when setting is toggled.
- Moved carrier and power notifications to bottom for bottom bar
  cannot make the notifications to appear aligned bottom. layout engine
  drives me mad. if you got a solution, please feedback.
- Created "Tablet tweaks" menu in cm-settings root to gather all tablet realted
  options in one place
- Extended power menu with home/menu/back buttons. toggable on the fly via cm
  settings
- Custom volume-long-press events (home/back/menu/call/end call/search/start-stop
  -music/next track/prev track/longpress home)
- Added same options for both-volume-buttons press and long-press (not fully implemented yet)
- Fixed status bar xml, so soft buttons now appear as big as the .png file is.
- Solved issue about soft buttons not clickable. Their size is now determined
  smart by the real size of the buttons
- Added option to move soft-buttons left or right
- Added submenu to choose which soft buttons to display.
- Added Quick-Notification-Area-Soft-Button - instantly opens/closes notification
  area since swiping it open is a long way on tablets
- Added a Dead-Zone option, so the middle of the status bar is not clickable.
  Happend a lot before people click it when trying to hit space
- Added option to toggle extended power items
- Added option to reverse power button behavior (switch short-press with long-press action)
- cleaned up the options and created new submenus
- complelty rewrote volume button handling
- integrated Drakknars great new design and wrote code for it
- added option to disable lockscreen
- added option to disable fullscreen
- disable ticker notifications if softbuttons enabled
- added hdpi icons for resized statusbar via overlay for vega and encore
  this way, status bar items dont look blury anymore
- added search button to list of soft-buttons - its off by default
- added long-press to home, back and search soft-button
- extended fullscreen handling: when a fullscreen app is running, an additional
  hide-softbutton is displayed. once pressed, the app gets real fullscreen
- added option to choose unhide button for fullscreen
- improved hide-button handling for special situation, like app-starting-app
  (i.e. astro file mananger starting movie player, which does fullscreen request)
- bugfix phase #1 - fix all known bugs but volume key handling (needs big rewrite)
- bugfix phase #2 - removed volume remapping for cm7stable, because source of too many
  possible bugs considering all the uses of volume buttons + lockscreen disable + reverse
- code cleanup - moved most stuff to Cm classes (CmSystem, CmPhoneWindowManager,
  CmStatusBarView, CmButtonTracker) - am satisfied with the code now
- improved fullscreen overriding in Window class. not only setFlags, but also setAttributes
  is intercepted now
- modified stock AndroidTerm to not crash anymore with our new fullscreen handling
- further improved fullscreen handling after all feedback i got. RC2 and probably merge
  ready code - although i still have to re-insert the trailing spaces

Thanks to Samuel Halff <samuelhalff@gmail.com>, who not only inspired
all this, but also did a first version of bottom status bar. Without
his initial work on the Status Bar and on the CM-Crew (telling this is
absolutly needed), this patch wouldnt exist.
Also thanks to the Nook Color community, where all those options were
discussed.

All graphics done by Stefano Pignataro (Drakknar@XDA) - again, awesome work mate (:

Settings part of this patch: http://review.cyanogenmod.com/4206

You can find Samuel's original patch here:
https://github.com/samuelhalff/android_frameworks_base/commits/gingerbread

You can find his thread from xda where this is discussed here: http://kan.gd/3vd

Change-Id: I51816a89a2c64ac0a83a377ea5f91a40d6fdd703
parent dd2f9438
Loading
Loading
Loading
Loading
+204 −0
Original line number Diff line number Diff line
/*
 * Created by Sven Dawitz; Copyright (C) 2011 CyanogenMod Project
 *
 * 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 android.provider;

import android.content.Context;
import android.view.KeyEvent;

import com.android.internal.R;

public final class CmSystem {
    // explaination of each default value in detail at
    // frameworks/base/core/res/res/value/config.xml
    // can be overridden system wide by overlay usage

    // sorted in order of appearance in tablet tweaks options menu
    public static final int CM_IS_TABLET=0;
    public static final int CM_HAS_SOFT_BUTTONS=1;

    public static final int CM_DEFAULT_BOTTOM_STATUS_BAR=2;
    public static final int CM_DEFAULT_USE_DEAD_ZONE=3;
    public static final int CM_DEFAULT_SOFT_BUTTONS_LEFT=4;

    public static final int CM_DEFAULT_SHOW_SOFT_HOME=5;
    public static final int CM_DEFAULT_SHOW_SOFT_MENU=6;
    public static final int CM_DEFAULT_SHOW_SOFT_BACK=7;
    public static final int CM_DEFAULT_SHOW_SOFT_SEARCH=8;
    public static final int CM_DEFAULT_SHOW_SOFT_QUICK_NA=9;

    public static final int CM_DEFAULT_DISABLE_LOCKSCREEN=10;
    public static final int CM_DEFAULT_DISABLE_FULLSCREEN=11;

    public static final int CM_DEFAULT_UNHIDE_BUTTON_INDEX=12;

    public static final int CM_DEFAULT_EXTEND_POWER_MENU=13;

    public static final int CM_DEFAULT_POWER_MENU_HOME=14;
    public static final int CM_DEFAULT_POWER_MENU_MENU=15;
    public static final int CM_DEFAULT_POWER_MENU_BACK=16;

    public static final int CM_DEFAULT_REVERSE_VOLUME_BEHAVIOR=17;
    public static final int CM_DEFAULT_REMAPPED_LONG_VOL_UP_INDEX=18;
    public static final int CM_DEFAULT_REMAPPED_LONG_VOL_DOWN_INDEX=19;
    public static final int CM_DEFAULT_REMAPPED_BOTH_VOL_INDEX=20;
    public static final int CM_DEFAULT_REMAPPED_LONG_BOTH_VOL_INDEX=21;

    // not a keycode, so negative value can never be considered keycode - user -1, -2, -3...
    // used in PhoneWindowManager
    public static final int VOLUME_ACTION_LONG_HOME = -1;
    public static final int VOLUME_ACTION_NONE = 0;
    public static final int KEYCODE_NONE = -1;


    public CmSystem(){
        //nothing to be done, as long as only static functions in here
    }

    public static boolean getDefaultBool(Context context, int which){
        int res=getResourceId(which);

        if(res!=0)
            return context.getResources().getBoolean(res);

        // default if id not found
        return false;
    }

    public static int getDefaultInt(Context context, int which){
        int res=getResourceId(which);

        if(res!=0)
            return context.getResources().getInteger(res);

        // default if id not found
        return 0;
    }

    private static int getResourceId(int which){
        int resId=0;

        switch(which){
            case CM_IS_TABLET:
                resId=R.bool.cm_default_is_tablet;
                break;
            case CM_HAS_SOFT_BUTTONS:
                resId=R.bool.cm_default_has_soft_buttons;
                break;

            case CM_DEFAULT_BOTTOM_STATUS_BAR:
                resId=R.bool.cm_default_bottom_status_bar;
                break;
            case CM_DEFAULT_USE_DEAD_ZONE:
                resId=R.bool.cm_default_use_dead_zone;
                break;
            case CM_DEFAULT_SOFT_BUTTONS_LEFT:
                resId=R.bool.cm_default_soft_buttons_left;
                break;

            case CM_DEFAULT_SHOW_SOFT_HOME:
                resId=R.bool.cm_default_show_soft_home;
                break;
            case CM_DEFAULT_SHOW_SOFT_MENU:
                resId=R.bool.cm_default_show_soft_menu;
                break;
            case CM_DEFAULT_SHOW_SOFT_BACK:
                resId=R.bool.cm_default_show_soft_back;
                break;
            case CM_DEFAULT_SHOW_SOFT_SEARCH:
                resId=R.bool.cm_default_show_soft_search;
                break;
            case CM_DEFAULT_SHOW_SOFT_QUICK_NA:
                resId=R.bool.cm_default_show_soft_quick_na;
                break;

            case CM_DEFAULT_DISABLE_LOCKSCREEN:
                resId=R.bool.cm_default_disable_lockscreen;
                break;
            case CM_DEFAULT_DISABLE_FULLSCREEN:
                resId=R.bool.cm_default_disable_fullscreen;
                break;

            case CM_DEFAULT_EXTEND_POWER_MENU:
                resId=R.bool.cm_default_extend_power_menu;
                break;

            case CM_DEFAULT_POWER_MENU_HOME:
                resId=R.bool.cm_default_power_menu_home;
                break;
            case CM_DEFAULT_POWER_MENU_MENU:
                resId=R.bool.cm_default_power_menu_menu;
                break;
            case CM_DEFAULT_POWER_MENU_BACK:
                resId=R.bool.cm_default_power_menu_back;
                break;

            case CM_DEFAULT_REVERSE_VOLUME_BEHAVIOR:
                resId=R.bool.cm_default_reverse_volume_behavior;
                break;

            // integer values
            case CM_DEFAULT_UNHIDE_BUTTON_INDEX:
                resId=R.integer.cm_default_unhide_button_index;
                break;
            case CM_DEFAULT_REMAPPED_LONG_VOL_UP_INDEX:
                resId=R.integer.cm_default_remapped_long_vol_up_index;
                break;
            case CM_DEFAULT_REMAPPED_LONG_VOL_DOWN_INDEX:
                resId=R.integer.cm_default_remapped_long_vol_down_index;
                break;
            case CM_DEFAULT_REMAPPED_BOTH_VOL_INDEX:
                resId=R.integer.cm_default_remapped_both_vol_index;
                break;
            case CM_DEFAULT_REMAPPED_LONG_BOTH_VOL_INDEX:
                resId=R.integer.cm_default_remapped_long_both_vol_index;
                break;
        }

        return resId;
    }

    // remaped indexes of CmParts' array.xml file
    public static int translateActionToKeycode(int longActionIndex) {
        switch (longActionIndex){
            case 1: return KeyEvent.KEYCODE_HOME;
            case 2: return KeyEvent.KEYCODE_MENU;
            case 3: return KeyEvent.KEYCODE_BACK;
            case 4: return KeyEvent.KEYCODE_SEARCH;
            case 5: return KeyEvent.KEYCODE_POWER;
            case 6: return KeyEvent.KEYCODE_CALL;
            case 7: return KeyEvent.KEYCODE_ENDCALL;
            case 8: return KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
            case 9: return KeyEvent.KEYCODE_MEDIA_NEXT;
            case 10: return KeyEvent.KEYCODE_MEDIA_PREVIOUS;
            case 11: return VOLUME_ACTION_LONG_HOME;
            default: return VOLUME_ACTION_NONE;
        }
    }

    // remaped indexes of CmParts' array.xml file
    public static final int translateUnhideIndexToKeycode(int unhideButtonIndex) {
        switch (unhideButtonIndex){
            case 1: return KeyEvent.KEYCODE_MENU;
            case 2: return KeyEvent.KEYCODE_BACK;
            case 3: return KeyEvent.KEYCODE_SEARCH;
            case 4: return KeyEvent.KEYCODE_CAMERA;
            case 5: return KeyEvent.KEYCODE_VOLUME_UP;
            case 6: return KeyEvent.KEYCODE_VOLUME_DOWN;
            default: return KeyEvent.KEYCODE_HOME;
        }
    }
}
+125 −0
Original line number Diff line number Diff line
@@ -2145,6 +2145,131 @@ public final class Settings {
         */
        public static final String STATUS_BAR_CLOCK = "status_bar_clock";

        /**
         * Whether to display the status bar on top or bottom
         * 0: show status bar on top (default for most devices)
         * 1: show status bar on bottom
         * default: 0 - can be overridden via CMParts config.xml for some devices
         * @hide
         */
        public static final String STATUS_BAR_BOTTOM = "status_bar_bottom";

        /**
         * Whether to add a dead zone to the middle of the status bar
         * 0: no dead zone
         * 1: enable dead zone
         * default: 0
         * @hide
         */
        public static final String STATUS_BAR_DEAD_ZONE = "status_bar_dead_zone";

        /**
         * 4 options which decide, which soft-buttons to show.
         * @hide
         */
        public static final String SOFT_BUTTON_SHOW_HOME = "soft_button_show_home";
        public static final String SOFT_BUTTON_SHOW_MENU = "soft_button_show_menu";
        public static final String SOFT_BUTTON_SHOW_BACK = "soft_button_show_back";
        public static final String SOFT_BUTTON_SHOW_SEARCH = "soft_button_show_search";
        public static final String SOFT_BUTTON_SHOW_QUICK_NA = "soft_button_show_quick_na";

        /**
         * Whether to display the soft buttons on left side
         * 0: shows them default right
         * 1: shows them left (overlaps with date display when dragging notification area open)
         * default: 0 - can be overridden via CMParts config.xml for some devices
         * @hide
         */
        public static final String SOFT_BUTTONS_LEFT = "soft_buttons_left";

        /**
         * Whether to override fullscreen so statusbar always visible
         * 0: default behavior - fullscreen hides status bar
         * 1: override fullscreen.
         * default: 0
         * @hide
         */
        public static final String FULLSCREEN_DISABLED = "fullscreen_disabled";

        /**
         * Whether to disable lockscreen
         * 0: default behavior - lockscreen shown when screen off
         * 1: override lockscreen
         * default: 0
         * @hide
         */
        public static final String LOCKSCREEN_DISABLED = "lockscreen_disabled";

        /**
         * Which key triggers unhide of statusbar in fullscreen mode
         * values described in array.xml of CMParts
         * default: 0 (power button)
         * @hide
         */
        public static final String UNHIDE_BUTTON = "unhide_button";

        /**
         * Whether to display extended option (home/menu/back) in power menu
         * 0: dont extend (default for most devices)
         * 1: extend
         * default: 0 - can be overridden via CMParts config.xml for some devices
         * @hide
         */
        public static final String EXTEND_PM = "extend_pm";

        /**
         * 3 options which decide, which contents extended power menu should include
         * @hide
         */
        public static final String EXTEND_PM_SHOW_HOME = "extend_pm_show_home";
        public static final String EXTEND_PM_SHOW_MENU = "extend_pm_show_menu";
        public static final String EXTEND_PM_SHOW_BACK = "extend_pm_show_back";

        /**
         * Reverses the volume button behavior
         * 0: press = volume, long-press = user action
         * 1: press = user action, long-press = volume
         * default: 0
         * @hide
         */
        public static final String REVERSE_VOLUME_BEHAVIOR = "reverse_volume_behavior";

        /**
         * Action to be executed on long-press-volume-plus while screen on
         * 0: none / default action
         * >0: action defined in arrays.xml of CMParts
         * default: 0
         * @hide
         */
        public static final String LONG_VOLP_ACTION = "long_volp_action";

        /**
         * Action to be executed on long-press-volume-minus while screen on
         * 0: none / default action
         * >0: action defined in arrays.xml of CMParts
         * default: 0
         * @hide
         */
        public static final String LONG_VOLM_ACTION = "long_volm_action";

        /**
         * Action to be executed on pressing both volume bottons while screen on
         * 0: none / default action
         * >0: action defined in arrays.xml of CMParts
         * default: 0
         * @hide
         */
        public static final String VOL_BOTH_ACTION = "vol_both_action";

        /**
         * Action to be executed on long-press both volume bottons while screen on
         * 0: none / default action
         * >0: action defined in arrays.xml of CMParts
         * default: 0
         * @hide
         */
        public static final String LONG_VOL_BOTH_ACTION = "long_vol_both_action";

        /**
         * Whether to wake the screen with the trackball. The value is boolean (1 or 0).
         * @hide
+73 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2006 The Android Open Source Project
 * Patched by Sven Dawitz; Copyright (C) 2011 CyanogenMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -16,7 +17,10 @@

package android.view;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
@@ -24,8 +28,13 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.CmSystem;
import android.provider.Settings;
import android.view.accessibility.AccessibilityEvent;

import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;;

/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
@@ -108,6 +117,31 @@ public abstract class Window {
    private int mDefaultWindowFormat = PixelFormat.OPAQUE;

    private boolean mHasSoftInputMode = false;
    private Intent mFullscreenAttemptIntent = null;
    private FullscreenReceiver mFullscreenReceiver=null;
    private String mForceFullscreenIntent = "android.intent.action.FORCE_FULLSCREEN";
    private String mRemoveFullscreenIntent = "android.intent.action.REMOVE_FULLSCREEN";

    class FullscreenReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent){
            final WindowManager.LayoutParams attrs = getAttributes();

            if(mForceFullscreenIntent.compareTo(intent.getAction())==0){
                context.sendBroadcast(new Intent("android.intent.action.FULLSCREEN_REAL_ON"));
                attrs.flags &= ~FLAG_FORCE_NOT_FULLSCREEN;
                attrs.flags |= FLAG_FULLSCREEN;
            }
            if(mRemoveFullscreenIntent.compareTo(intent.getAction())==0){
                context.sendBroadcast(new Intent("android.intent.action.FULLSCREEN_REAL_OFF"));
                attrs.flags &= ~FLAG_FULLSCREEN;
                attrs.flags |= FLAG_FORCE_NOT_FULLSCREEN;
            }

            if (mCallback != null) {
                mCallback.onWindowAttributesChanged(attrs);
            }
        }
    }

    // The current window attributes.
    private final WindowManager.LayoutParams mWindowAttributes =
@@ -298,6 +332,13 @@ public abstract class Window {
        mContext = context;
    }

    @Override
    protected void finalize() throws Throwable {
        if(mFullscreenReceiver!=null)
            mContext.unregisterReceiver(mFullscreenReceiver);
        super.finalize();
    }

    /**
     * Return the Context this window policy is running in, for retrieving
     * resources and other information.
@@ -647,6 +688,9 @@ public abstract class Window {
     */
    public void setFlags(int flags, int mask) {
        final WindowManager.LayoutParams attrs = getAttributes();

        flags=interceptFsRequest(flags);

        attrs.flags = (attrs.flags&~mask) | (flags&mask);
        mForcedWindowFlags |= mask;
        if (mCallback != null) {
@@ -665,6 +709,7 @@ public abstract class Window {
     *          current values.
     */
    public void setAttributes(WindowManager.LayoutParams a) {
        a.flags=interceptFsRequest(a.flags);
        mWindowAttributes.copyFrom(a);
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(mWindowAttributes);
@@ -1051,4 +1096,31 @@ public abstract class Window {
     */
    public abstract int getVolumeControlStream();
    
    protected int interceptFsRequest(int inFlags){
        int result=inFlags;

        // override fullscreen if selected in tablet tweaks
        if((result&FLAG_FULLSCREEN) == FLAG_FULLSCREEN){
            int defValue=(CmSystem.getDefaultBool(mContext, CmSystem.CM_DEFAULT_DISABLE_FULLSCREEN) ? 1 : 0);
            boolean disableFullscreen=(Settings.System.getInt(mContext.getContentResolver(),
                    Settings.System.FULLSCREEN_DISABLED, defValue) == 1);
            if(disableFullscreen){
                // modify flags
                result&= ~FLAG_FULLSCREEN;
                result|= FLAG_FORCE_NOT_FULLSCREEN;
                // broadcast to StatusBarView
                if(mFullscreenAttemptIntent==null)
                    mFullscreenAttemptIntent=new Intent("android.intent.action.FULLSCREEN_ATTEMPT");
                mContext.sendBroadcast(mFullscreenAttemptIntent);
                // set up the receiver for fullscreen callback from status bar and phonewindowmanager
                if(mFullscreenReceiver==null){
                    mFullscreenReceiver=new FullscreenReceiver();
                    mContext.registerReceiver(mFullscreenReceiver, new IntentFilter(mForceFullscreenIntent));
                    mContext.registerReceiver(mFullscreenReceiver, new IntentFilter(mRemoveFullscreenIntent));
                }
            }
        }

        return result;
    }
}
+932 B
Loading image diff...
+1.95 KiB
Loading image diff...
Loading