improved keyboard navigation

This commit is contained in:
Mariotaku Lee 2015-10-07 22:09:00 +08:00
parent cb4c6a234a
commit 826e4bc7de
25 changed files with 340 additions and 213 deletions

View File

@ -68,6 +68,7 @@ public abstract class BasePreferenceActivity extends AppCompatPreferenceActivity
private String mCurrentThemeFontFamily;
@Inject
protected ActivityTracker mActivityTracker;
private int mMetaState;
@Override
protected void onStart() {
@ -147,12 +148,12 @@ public abstract class BasePreferenceActivity extends AppCompatPreferenceActivity
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return false;
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return false;
}
@ -170,13 +171,20 @@ public abstract class BasePreferenceActivity extends AppCompatPreferenceActivity
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (handleKeyboardShortcutSingle(mKeyboardShortcutsHandler, keyCode, event)) return true;
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
if (handleKeyboardShortcutSingle(mKeyboardShortcutsHandler, keyCode, event, mMetaState))
return true;
return super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
if (handleKeyboardShortcutRepeat(mKeyboardShortcutsHandler, keyCode, event.getRepeatCount(), event))
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
if (handleKeyboardShortcutRepeat(mKeyboardShortcutsHandler, keyCode, event.getRepeatCount(), event, mMetaState))
return true;
return super.onKeyDown(keyCode, event);
}

View File

@ -48,6 +48,7 @@ public class KeyboardShortcutPreferenceCompatActivity extends BaseThemedActivity
private KeyboardShortcutSpec mKeySpec;
private Button mButtonPositive, mButtonNegative, mButtonNeutral;
private int mMetaState;
@Override
public String getThemeBackgroundOption() {
@ -97,11 +98,23 @@ public class KeyboardShortcutPreferenceCompatActivity extends BaseThemedActivity
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
final String keyAction = getKeyAction();
if (keyAction == null) return false;
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(getContextTag(), keyCode, event);
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(getContextTag(),
keyCode, event, KeyEvent.normalizeMetaState(mMetaState | event.getMetaState()));
if (spec == null || !spec.isValid()) {
return super.onKeyUp(keyCode, event);
}

View File

@ -235,24 +235,24 @@ public class SettingsActivity extends BasePreferenceActivity {
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_BACK.equals(action)) {
navigateUp();
return true;
}
return super.handleKeyboardShortcutSingle(handler, keyCode, event);
return super.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
return ACTION_NAVIGATION_BACK.equals(action);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override

View File

@ -15,6 +15,8 @@ public interface IControlBarActivity {
void setControlBarVisibleAnimate(boolean visible);
void setControlBarVisibleAnimate(boolean visible, ControlBarShowHideHelper.ControlBarAnimationListener listener);
float getControlBarOffset();
int getControlBarHeight();
@ -58,7 +60,15 @@ public interface IControlBarActivity {
}
}
public interface ControlBarAnimationListener {
void onControlBarVisibleAnimationFinish(boolean visible);
}
public void setControlBarVisibleAnimate(boolean visible) {
setControlBarVisibleAnimate(visible, null);
}
public void setControlBarVisibleAnimate(final boolean visible, final ControlBarAnimationListener listener) {
if (mControlAnimationDirection != 0) return;
final ObjectAnimator animator;
final float offset = mActivity.getControlBarOffset();
@ -78,6 +88,9 @@ public interface IControlBarActivity {
@Override
public void onAnimationEnd(Animator animation) {
mControlAnimationDirection = 0;
if (listener != null) {
listener.onControlBarVisibleAnimationFinish(visible);
}
}
@Override

View File

@ -71,6 +71,7 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
private boolean mInstanceStateSaved;
private boolean mIsVisible;
private Rect mSystemWindowsInsets;
private int mMetaState;
@Override
public boolean getSystemWindowsInsets(Rect insets) {
@ -109,15 +110,22 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (handleKeyboardShortcutSingle(mKeyboardShortcutsHandler, keyCode, event)) return true;
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event) || super.onKeyUp(keyCode, event);
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
if (handleKeyboardShortcutSingle(mKeyboardShortcutsHandler, keyCode, event, mMetaState))
return true;
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event, mMetaState) || super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (handleKeyboardShortcutRepeat(mKeyboardShortcutsHandler, keyCode, event.getRepeatCount(), event))
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
if (handleKeyboardShortcutRepeat(mKeyboardShortcutsHandler, keyCode, event.getRepeatCount(), event, mMetaState))
return true;
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event) || super.onKeyDown(keyCode, event);
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event, mMetaState) || super.onKeyDown(keyCode, event);
}
@Override
@ -137,17 +145,17 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return false;
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return false;
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return false;
}
@ -205,6 +213,11 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
}
@Override
public void setControlBarVisibleAnimate(boolean visible, ControlBarShowHideHelper.ControlBarAnimationListener listener) {
}
@Override
public float getControlBarOffset() {
return 0;

View File

@ -774,8 +774,8 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_BACK.equals(action)) {
if (mEditText.length() == 0 && !mTextChanged) {
if (!mNavigateBackPressed) {
@ -796,12 +796,12 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
}
return true;
}
return super.handleKeyboardShortcutSingle(handler, keyCode, event);
return super.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
private void addMedia(final ParcelableMediaUpdate media) {

View File

@ -207,6 +207,11 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible);
}
@Override
public void setControlBarVisibleAnimate(boolean visible, ControlBarShowHideHelper.ControlBarAnimationListener listener) {
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible, listener);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
@ -235,9 +240,9 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event)) return true;
String action = handler.getKeyAction(CONTEXT_TAG_HOME, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event, metaState)) return true;
String action = handler.getKeyAction(CONTEXT_TAG_HOME, keyCode, event, metaState);
if (action != null) {
switch (action) {
case ACTION_HOME_ACCOUNTS_DASHBOARD: {
@ -251,7 +256,7 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
}
}
}
action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action != null) {
switch (action) {
case ACTION_NAVIGATION_PREVIOUS_TAB: {
@ -284,19 +289,20 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
}
}
}
return handler.handleKey(this, null, keyCode, event);
return handler.handleKey(this, null, keyCode, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event)) return true;
return super.isKeyboardShortcutHandled(handler, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event, metaState)) return true;
return super.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
if (handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event)) return true;
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
if (handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState))
return true;
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
@ -643,28 +649,32 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
private boolean handleFragmentKeyboardShortcutRepeat(final KeyboardShortcutsHandler handler,
final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
@NonNull final KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode,
repeatCount, event, metaState);
}
return false;
}
private boolean handleFragmentKeyboardShortcutSingle(final KeyboardShortcutsHandler handler,
final int keyCode, @NonNull final KeyEvent event) {
final int keyCode, @NonNull final KeyEvent event,
int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode,
event, metaState);
}
return false;
}
private boolean isFragmentKeyboardShortcutHandled(final KeyboardShortcutsHandler handler,
final int keyCode, @NonNull final KeyEvent event) {
final int keyCode, @NonNull final KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode,
event, metaState);
}
return false;
}

View File

@ -165,17 +165,17 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (shouldFragmentTakeAllKeyboardShortcuts()) {
return handleFragmentKeyboardShortcutSingle(handler, keyCode, event);
return handleFragmentKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event, metaState)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_BACK.equals(action)) {
onBackPressed();
return true;
}
return handler.handleKey(this, null, keyCode, event);
return handler.handleKey(this, null, keyCode, event, metaState);
}
private boolean shouldFragmentTakeAllKeyboardShortcuts() {
@ -184,25 +184,26 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
if (shouldFragmentTakeAllKeyboardShortcuts()) {
handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
if (handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event)) return true;
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
if (handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState))
return true;
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event)) return true;
return super.isKeyboardShortcutHandled(handler, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event, metaState)) return true;
return super.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
private boolean isFragmentKeyboardShortcutHandled(final KeyboardShortcutsHandler handler,
final int keyCode, @NonNull final KeyEvent event) {
final int keyCode, @NonNull final KeyEvent event, int metaState) {
final Fragment fragment = getCurrentVisibleFragment();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
return false;
}
@ -301,20 +302,21 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
}
private boolean handleFragmentKeyboardShortcutRepeat(KeyboardShortcutsHandler handler, int keyCode,
int repeatCount, @NonNull KeyEvent event) {
int repeatCount, @NonNull KeyEvent event, int metaState) {
final Fragment fragment = getCurrentVisibleFragment();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode,
repeatCount, event);
repeatCount, event, metaState);
}
return false;
}
private boolean handleFragmentKeyboardShortcutSingle(KeyboardShortcutsHandler handler, int keyCode,
@NonNull KeyEvent event) {
@NonNull KeyEvent event, int metaState) {
final Fragment fragment = getCurrentVisibleFragment();
if (fragment instanceof KeyboardShortcutCallback) {
if (((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode, event)) {
if (((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode,
event, metaState)) {
return true;
}
}
@ -558,6 +560,13 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible);
}
@Override
public void setControlBarVisibleAnimate(boolean visible, ControlBarShowHideHelper.ControlBarAnimationListener listener) {
// Currently only search page needs this pattern, so we only enable this feature for it.
if (!(getCurrentVisibleFragment() instanceof SearchFragment)) return;
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible, listener);
}
@Override
public float getControlBarOffset() {
return 1 + mActionBarContainer.getTranslationY() / (float) getControlBarHeight();

View File

@ -184,8 +184,8 @@ public final class MediaViewerActivity extends BaseAppCompatActivity implements
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action != null) {
switch (action) {
case ACTION_NAVIGATION_PREVIOUS_TAB: {
@ -210,7 +210,7 @@ public final class MediaViewerActivity extends BaseAppCompatActivity implements
}
}
}
return super.handleKeyboardShortcutSingle(handler, keyCode, event);
return super.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override

View File

@ -192,8 +192,8 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_BACK.equals(action) && mSearchQuery.length() == 0) {
if (!mTextChanged) {
onBackPressed();
@ -202,7 +202,7 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
}
return true;
}
return super.handleKeyboardShortcutSingle(handler, keyCode, event);
return super.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override

View File

@ -68,6 +68,7 @@ public abstract class ThemedFragmentActivity extends FragmentActivity implements
private int mProfileImageStyle;
private String mCurrentThemeBackgroundOption;
private String mCurrentThemeFontFamily;
private int mMetaState;
@NonNull
@Override
@ -166,31 +167,37 @@ public abstract class ThemedFragmentActivity extends FragmentActivity implements
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return false;
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return false;
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return false;
}
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
handleKeyboardShortcutSingle(mKeyboardShortcutsHandler, keyCode, event);
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event) || super.onKeyUp(keyCode, event);
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
handleKeyboardShortcutSingle(mKeyboardShortcutsHandler, keyCode, event, mMetaState);
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event, mMetaState) || super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (handleKeyboardShortcutRepeat(mKeyboardShortcutsHandler, keyCode, event.getRepeatCount(), event))
if (KeyEvent.isModifierKey(keyCode)) {
mMetaState |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
if (handleKeyboardShortcutRepeat(mKeyboardShortcutsHandler, keyCode, event.getRepeatCount(), event, mMetaState))
return true;
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event) || super.onKeyDown(keyCode, event);
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event, mMetaState) || super.onKeyDown(keyCode, event);
}
@Override

View File

@ -147,6 +147,7 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
private final OnSharedPreferenceChangeListener mPreferencesChangeListener;
private TextView mKeysLabel, mConflictLabel;
private KeyboardShortcutSpec mKeySpec;
private int mModifierStates;
public KeyboardShortcutPreference(final Context context, final KeyboardShortcutsHandler handler,
@Nullable final String contextTag, @NonNull final String action) {
@ -170,8 +171,18 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_UP) return false;
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(mContextTag, keyCode, event);
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (KeyEvent.isModifierKey(keyCode)) {
mModifierStates |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
} else if (event.getAction() != KeyEvent.ACTION_UP) {
return false;
}
if (KeyEvent.isModifierKey(keyCode)) {
mModifierStates &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
}
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(mContextTag,
keyCode, event, KeyEvent.normalizeMetaState(mModifierStates | event.getMetaState()));
if (spec == null || !spec.isValid()) {
Log.d(LOGTAG, String.format("Invalid key %s", event), new Exception());
return false;

View File

@ -73,19 +73,19 @@ public abstract class AbsActivitiesFragment<Data> extends AbsContentRecyclerView
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
@NonNull final KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, final int keyCode, @NonNull final KeyEvent event) {
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, final int keyCode, @NonNull final KeyEvent event, int metaState) {
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
public SharedPreferences getSharedPreferences() {

View File

@ -60,7 +60,7 @@ import org.mariotaku.twidere.view.themed.AccentSwipeRefreshLayout;
*/
public abstract class AbsContentRecyclerViewFragment<A extends LoadMoreSupportAdapter> extends BaseSupportFragment
implements OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, ControlBarOffsetListener,
ContentListSupport {
ContentListSupport, IControlBarActivity.ControlBarShowHideHelper.ControlBarAnimationListener {
private View mProgressContainer;
private SwipeRefreshLayout mSwipeRefreshLayout;
@ -129,11 +129,16 @@ public abstract class AbsContentRecyclerViewFragment<A extends LoadMoreSupportAd
return true;
}
@Override
public void onControlBarVisibleAnimationFinish(boolean visible) {
updateRefreshProgressOffset();
}
@Override
public void setControlVisible(boolean visible) {
final FragmentActivity activity = getActivity();
if (activity instanceof IControlBarActivity) {
((IControlBarActivity) activity).setControlBarVisibleAnimate(visible);
((IControlBarActivity) activity).setControlBarVisibleAnimate(visible, this);
}
}

View File

@ -144,8 +144,8 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentRecyclerViewFr
public abstract boolean getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds);
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_REFRESH.equals(action)) {
triggerRefresh();
return true;
@ -153,56 +153,56 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentRecyclerViewFr
final RecyclerView recyclerView = getRecyclerView();
final LinearLayoutManager layoutManager = getLayoutManager();
if (recyclerView == null || layoutManager == null) return false;
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(recyclerView, layoutManager.getFocusedChild());
final int position;
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(recyclerView,
layoutManager.getFocusedChild());
int position = -1;
if (focusedChild != null && focusedChild.getParent() == recyclerView) {
position = recyclerView.getChildLayoutPosition(focusedChild);
} else {
return false;
}
if (position == -1) return false;
final ParcelableStatus status = getAdapter().getStatus(position);
if (status == null) return false;
if (keyCode == KeyEvent.KEYCODE_ENTER) {
Utils.openStatus(getActivity(), status, null);
return true;
}
if (action == null) {
action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event);
}
if (action == null) return false;
switch (action) {
case ACTION_STATUS_REPLY: {
final Intent intent = new Intent(INTENT_ACTION_REPLY);
intent.putExtra(EXTRA_STATUS, status);
startActivity(intent);
if (position != -1) {
final ParcelableStatus status = getAdapter().getStatus(position);
if (status == null) return false;
if (keyCode == KeyEvent.KEYCODE_ENTER) {
Utils.openStatus(getActivity(), status, null);
return true;
}
case ACTION_STATUS_RETWEET: {
RetweetQuoteDialogFragment.show(getFragmentManager(), status);
return true;
if (action == null) {
action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event, metaState);
}
case ACTION_STATUS_FAVORITE: {
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
} else {
twitter.createFavoriteAsync(status.account_id, status.id);
if (action == null) return false;
switch (action) {
case ACTION_STATUS_REPLY: {
final Intent intent = new Intent(INTENT_ACTION_REPLY);
intent.putExtra(EXTRA_STATUS, status);
startActivity(intent);
return true;
}
case ACTION_STATUS_RETWEET: {
RetweetQuoteDialogFragment.show(getFragmentManager(), status);
return true;
}
case ACTION_STATUS_FAVORITE: {
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
} else {
twitter.createFavoriteAsync(status.account_id, status.id);
}
return true;
}
return true;
}
}
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event);
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_REFRESH.equals(action)) {
return true;
}
if (action == null) {
action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event);
action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event, metaState);
}
if (action == null) return false;
switch (action) {
@ -211,13 +211,13 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentRecyclerViewFr
case ACTION_STATUS_FAVORITE:
return true;
}
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event);
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
@NonNull final KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override

View File

@ -53,18 +53,18 @@ abstract class AbsUserListsFragment<Data> extends AbsContentRecyclerViewFragment
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
@Override

View File

@ -52,18 +52,18 @@ abstract class AbsUsersFragment<Data> extends AbsContentRecyclerViewFragment<Abs
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
@Override

View File

@ -156,21 +156,21 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo
@Override
public boolean handleKeyboardShortcutSingle(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, @NonNull final KeyEvent event) {
final int keyCode, @NonNull final KeyEvent event, int metaState) {
return false;
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
return ACTION_NAVIGATION_PREVIOUS.equals(action) || ACTION_NAVIGATION_NEXT.equals(action);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
@NonNull final KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action == null) return false;
final int offset;
switch (action) {

View File

@ -120,14 +120,14 @@ public class DirectMessagesFragment extends AbsContentRecyclerViewFragment<Messa
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
@NonNull final KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, @NonNull final KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
final int keyCode, @NonNull final KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_REFRESH.equals(action)) {
triggerRefresh();
return true;
@ -136,9 +136,9 @@ public class DirectMessagesFragment extends AbsContentRecyclerViewFragment<Messa
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
return ACTION_NAVIGATION_REFRESH.equals(action) || mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
return ACTION_NAVIGATION_REFRESH.equals(action) || mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}

View File

@ -522,8 +522,8 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (ACTION_NAVIGATION_BACK.equals(action)) {
final boolean showingConversation = isShowingConversation();
final EditText editText = showingConversation ? mEditText : mEditUserQuery;
@ -553,13 +553,13 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
return ACTION_NAVIGATION_BACK.equals(action);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return false;
}

View File

@ -20,9 +20,9 @@
package org.mariotaku.twidere.fragment.support;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
@ -106,9 +106,9 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event, metaState)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action != null) {
switch (action) {
case ACTION_NAVIGATION_PREVIOUS_TAB: {
@ -127,29 +127,26 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
}
}
}
return handler.handleKey(getActivity(), null, keyCode, event);
return handler.handleKey(getActivity(), null, keyCode, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event, metaState)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
return ACTION_NAVIGATION_PREVIOUS_TAB.equals(action) || ACTION_NAVIGATION_NEXT_TAB.equals(action);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
return handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
}
public void hideIndicator() {
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
return handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof IControlBarActivity) {
((IControlBarActivity) activity).registerControlBarOffsetListener(this);
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof IControlBarActivity) {
((IControlBarActivity) context).registerControlBarOffsetListener(this);
}
}
@ -323,26 +320,32 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
return getCurrentVisibleFragment();
}
private boolean handleFragmentKeyboardShortcutRepeat(KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
private boolean handleFragmentKeyboardShortcutRepeat(KeyboardShortcutsHandler handler, int keyCode,
int repeatCount, @NonNull KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode,
repeatCount, event, metaState);
}
return false;
}
private boolean handleFragmentKeyboardShortcutSingle(KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
private boolean handleFragmentKeyboardShortcutSingle(KeyboardShortcutsHandler handler, int keyCode,
@NonNull KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode,
event, metaState);
}
return false;
}
private boolean isFragmentKeyboardShortcutHandled(KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
private boolean isFragmentKeyboardShortcutHandled(KeyboardShortcutsHandler handler, int keyCode,
@NonNull KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode,
event, metaState);
}
return false;
}

View File

@ -386,7 +386,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (!KeyboardShortcutsHandler.isValidForHotkey(keyCode, event)) return false;
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(mRecyclerView, mLayoutManager.getFocusedChild());
final int position;
@ -398,7 +398,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
if (position == -1) return false;
final ParcelableStatus status = getAdapter().getStatus(position);
if (status == null) return false;
String action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event);
String action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event, metaState);
if (action == null) return false;
switch (action) {
case ACTION_STATUS_REPLY: {
@ -425,8 +425,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_STATUS, keyCode, event, metaState);
if (action == null) return false;
switch (action) {
case ACTION_STATUS_REPLY:
@ -434,15 +434,15 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
case ACTION_STATUS_FAVORITE:
return true;
}
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event);
return mNavigationHelper.isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
@NonNull final KeyEvent event, int metaState) {
return mNavigationHelper.handleKeyboardShortcutRepeat(handler, keyCode,
repeatCount, event);
repeatCount, event, metaState);
}

View File

@ -1116,9 +1116,9 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event, metaState)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action != null) {
switch (action) {
case ACTION_NAVIGATION_PREVIOUS_TAB: {
@ -1137,13 +1137,13 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
}
}
}
return handler.handleKey(getActivity(), null, keyCode, event);
return handler.handleKey(getActivity(), null, keyCode, event, metaState);
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event, metaState)) return true;
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action != null) {
switch (action) {
case ACTION_NAVIGATION_PREVIOUS_TAB:
@ -1157,30 +1157,33 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
return handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
@NonNull final KeyEvent event, int metaState) {
return handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
private boolean handleFragmentKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
private boolean handleFragmentKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler,
int keyCode, int repeatCount, @NonNull KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState);
}
return false;
}
private boolean handleFragmentKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
private boolean handleFragmentKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler,
int keyCode, @NonNull KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode, event, metaState);
}
return false;
}
private boolean isFragmentKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
private boolean isFragmentKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler,
int keyCode, @NonNull KeyEvent event, int metaState) {
final Fragment fragment = getKeyboardShortcutRecipient();
if (fragment instanceof KeyboardShortcutCallback) {
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event);
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event, metaState);
}
return false;
}

View File

@ -23,6 +23,12 @@ import java.util.Map.Entry;
public class KeyboardShortcutsHandler implements Constants, KeyboardShortcutConstants {
public static final int MODIFIER_FLAG_CTRL = 0x00000001;
public static final int MODIFIER_FLAG_SHIFT = 0x00000002;
public static final int MODIFIER_FLAG_ALT = 0x00000004;
public static final int MODIFIER_FLAG_META = 0x00000008;
public static final int MODIFIER_FLAG_FN = 0x000000010;
private static final String KEYCODE_STRING_PREFIX = "KEYCODE_";
private static final HashMap<String, Integer> sActionLabelMap = new HashMap<>();
@ -80,23 +86,23 @@ public class KeyboardShortcutsHandler implements Constants, KeyboardShortcutCons
}
@Nullable
public String getKeyAction(final String contextTag, final int keyCode, final KeyEvent event) {
public String getKeyAction(final String contextTag, final int keyCode, final KeyEvent event, int metaState) {
if (!isValidForHotkey(keyCode, event)) return null;
final String key = getKeyEventKey(contextTag, keyCode, event);
final String key = getKeyEventKey(contextTag, keyCode, event, metaState);
return mPreferences.getString(key, null);
}
public static String getKeyEventKey(String contextTag, int keyCode, KeyEvent event) {
public static String getKeyEventKey(String contextTag, int keyCode, KeyEvent event, int metaState) {
if (!isValidForHotkey(keyCode, event)) return null;
final StringBuilder keyNameBuilder = new StringBuilder();
if (!TextUtils.isEmpty(contextTag)) {
keyNameBuilder.append(contextTag);
keyNameBuilder.append(".");
}
final int metaState = KeyEvent.normalizeMetaState(event.getMetaState());
final int normalizedMetaState = KeyEvent.normalizeMetaState(metaState | event.getMetaState());
for (int i = 0, j = sMetaNameMap.size(); i < j; i++) {
if ((sMetaNameMap.keyAt(i) & metaState) != 0) {
if ((sMetaNameMap.keyAt(i) & normalizedMetaState) != 0) {
keyNameBuilder.append(sMetaNameMap.valueAt(i));
keyNameBuilder.append("+");
}
@ -132,9 +138,8 @@ public class KeyboardShortcutsHandler implements Constants, KeyboardShortcutCons
return 0;
}
public static KeyboardShortcutSpec getKeyboardShortcutSpec(String contextTag, int keyCode, KeyEvent event) {
public static KeyboardShortcutSpec getKeyboardShortcutSpec(String contextTag, int keyCode, KeyEvent event, int metaState) {
if (!isValidForHotkey(keyCode, event)) return null;
final int metaState = KeyEvent.normalizeMetaState(event.getMetaState());
int metaStateNormalized = 0;
for (int i = 0, j = sMetaNameMap.size(); i < j; i++) {
if ((sMetaNameMap.keyAt(i) & metaState) != 0) {
@ -149,8 +154,8 @@ public class KeyboardShortcutsHandler implements Constants, KeyboardShortcutCons
return null;
}
public boolean handleKey(final Context context, final String contextTag, final int keyCode, final KeyEvent event) {
final String action = getKeyAction(contextTag, keyCode, event);
public boolean handleKey(final Context context, final String contextTag, final int keyCode, final KeyEvent event, int metaState) {
final String action = getKeyAction(contextTag, keyCode, event, metaState);
if (action == null) return false;
switch (action) {
case ACTION_COMPOSE: {
@ -250,13 +255,40 @@ public class KeyboardShortcutsHandler implements Constants, KeyboardShortcutCons
mPreferences.unregisterOnSharedPreferenceChangeListener(listener);
}
public static int getMetaStateForKeyCode(int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_CTRL_LEFT:
return KeyEvent.META_CTRL_LEFT_ON;
case KeyEvent.KEYCODE_CTRL_RIGHT:
return KeyEvent.META_CTRL_RIGHT_ON;
case KeyEvent.KEYCODE_SHIFT_LEFT:
return KeyEvent.META_SHIFT_LEFT_ON;
case KeyEvent.KEYCODE_SHIFT_RIGHT:
return KeyEvent.META_SHIFT_RIGHT_ON;
case KeyEvent.KEYCODE_ALT_LEFT:
return KeyEvent.META_ALT_LEFT_ON;
case KeyEvent.KEYCODE_ALT_RIGHT:
return KeyEvent.META_ALT_RIGHT_ON;
case KeyEvent.KEYCODE_META_LEFT:
return KeyEvent.META_META_LEFT_ON;
case KeyEvent.KEYCODE_META_RIGHT:
return KeyEvent.META_META_RIGHT_ON;
case KeyEvent.KEYCODE_FUNCTION:
return KeyEvent.META_FUNCTION_ON;
}
return 0;
}
public interface KeyboardShortcutCallback extends KeyboardShortcutConstants {
boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event);
boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode,
int repeatCount, @NonNull KeyEvent event, int metaState);
boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event);
boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode,
@NonNull KeyEvent event, int metaState);
boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event);
boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode,
@NonNull KeyEvent event, int metaState);
}
public interface TakeAllKeyboardShortcut {

View File

@ -59,8 +59,8 @@ public class RecyclerViewNavigationHelper implements KeyboardShortcutCallback {
@Override
public boolean handleKeyboardShortcutRepeat(@NonNull final KeyboardShortcutsHandler handler,
final int keyCode, final int repeatCount,
@NonNull final KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
@NonNull final KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action == null) return false;
final int direction;
switch (action) {
@ -109,8 +109,8 @@ public class RecyclerViewNavigationHelper implements KeyboardShortcutCallback {
}
@Override
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action == null) return false;
switch (action) {
case ACTION_NAVIGATION_TOP: {
@ -124,8 +124,8 @@ public class RecyclerViewNavigationHelper implements KeyboardShortcutCallback {
}
@Override
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event, int metaState) {
final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
if (action == null) return false;
switch (action) {
case ACTION_NAVIGATION_PREVIOUS: