mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 140609: navigating menu bar with arrows is reversed when UI aligned to the right. r=dean_tessman@hotmail.com, sr=jst.
This commit is contained in:
parent
2958cb7ad5
commit
8b17163212
@ -71,7 +71,7 @@ public:
|
||||
NS_IMETHOD Escape(PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD Enter() = 0;
|
||||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag) = 0;
|
||||
|
||||
NS_IMETHOD GetMenuParent(nsIMenuParent** aMenuParent) = 0;
|
||||
NS_IMETHOD GetMenuChild(nsIFrame** aResult) = 0;
|
||||
|
@ -52,6 +52,89 @@ class nsIDOMKeyEvent;
|
||||
* refcounted. Eventually it should not inherit from nsISupports.
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsNavigationDirection: an enum expressing navigation through the menus in
|
||||
* terms which are independent of the directionality of the chrome. The
|
||||
* terminology, derived from XSL-FO and CSS3 (e.g.
|
||||
* http://www.w3.org/TR/css3-text/#TextLayout), is BASE (Before, After, Start,
|
||||
* End), with the addition of First and Last (mapped to Home and End
|
||||
* respectively).
|
||||
*
|
||||
* In languages such as English where the inline progression is left-to-right
|
||||
* and the block progression is top-to-bottom (lr-tb), these terms will map out
|
||||
* as in the following diagram
|
||||
*
|
||||
* --- inline progression --->
|
||||
*
|
||||
* First |
|
||||
* ... |
|
||||
* Before |
|
||||
* +--------+ block
|
||||
* Start | | End progression
|
||||
* +--------+ |
|
||||
* After |
|
||||
* ... |
|
||||
* Last V
|
||||
*
|
||||
*/
|
||||
|
||||
enum nsNavigationDirection {
|
||||
eNavigationDirection_Last,
|
||||
eNavigationDirection_First,
|
||||
eNavigationDirection_Start,
|
||||
eNavigationDirection_Before,
|
||||
eNavigationDirection_End,
|
||||
eNavigationDirection_After
|
||||
};
|
||||
|
||||
#define NS_DIRECTION_IS_INLINE(dir) (dir == eNavigationDirection_Start || \
|
||||
dir == eNavigationDirection_End)
|
||||
#define NS_DIRECTION_IS_BLOCK(dir) (dir == eNavigationDirection_Before || \
|
||||
dir == eNavigationDirection_After)
|
||||
#define NS_DIRECTION_IS_BLOCK_TO_EDGE(dir) (dir == eNavigationDirection_First || \
|
||||
dir == eNavigationDirection_Last)
|
||||
|
||||
/**
|
||||
* DirectionFromKeyCode_lr_tb: an array that maps keycodes to values of
|
||||
* nsNavigationDirection for left-to-right and top-to-bottom flow orientation
|
||||
*/
|
||||
static nsNavigationDirection DirectionFromKeyCode_lr_tb [6] = {
|
||||
eNavigationDirection_Last, // NS_VK_END
|
||||
eNavigationDirection_First, // NS_VK_HOME
|
||||
eNavigationDirection_Start, // NS_VK_LEFT
|
||||
eNavigationDirection_Before, // NS_VK_UP
|
||||
eNavigationDirection_End, // NS_VK_RIGHT
|
||||
eNavigationDirection_After // NS_VK_DOWN
|
||||
};
|
||||
|
||||
/**
|
||||
* DirectionFromKeyCode_rl_tb: an array that maps keycodes to values of
|
||||
* nsNavigationDirection for right-to-left and top-to-bottom flow orientation
|
||||
*/
|
||||
static nsNavigationDirection DirectionFromKeyCode_rl_tb [6] = {
|
||||
eNavigationDirection_Last, // NS_VK_END
|
||||
eNavigationDirection_First, // NS_VK_HOME
|
||||
eNavigationDirection_End, // NS_VK_LEFT
|
||||
eNavigationDirection_Before, // NS_VK_UP
|
||||
eNavigationDirection_Start, // NS_VK_RIGHT
|
||||
eNavigationDirection_After // NS_VK_DOWN
|
||||
};
|
||||
|
||||
#ifdef IBMBIDI
|
||||
#define NS_DIRECTION_FROM_KEY_CODE(direction, keycode) \
|
||||
NS_ASSERTION(keycode >= NS_VK_END && keycode <= NS_VK_DOWN, \
|
||||
"Illegal key code"); \
|
||||
const nsStyleVisibility* vis = (const nsStyleVisibility*) \
|
||||
mStyleContext->GetStyleData(eStyleStruct_Visibility); \
|
||||
if (vis->mDirection == NS_STYLE_DIRECTION_RTL) \
|
||||
direction = DirectionFromKeyCode_rl_tb[keycode - NS_VK_END]; \
|
||||
else \
|
||||
direction = DirectionFromKeyCode_lr_tb[keycode - NS_VK_END];
|
||||
#else
|
||||
#define NS_DIRECTION_FROM_KEY_CODE(direction, keycode) \
|
||||
direction = DirectionFromKeyCode_lr_tb[keycode - NS_VK_END];
|
||||
#endif
|
||||
|
||||
class nsIMenuParent : public nsISupports {
|
||||
|
||||
public:
|
||||
@ -78,7 +161,7 @@ public:
|
||||
NS_IMETHOD RemoveKeyboardNavigator() = 0;
|
||||
|
||||
// Used to move up, down, left, and right in menus.
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag) = 0;
|
||||
// Called when the ESC key is held down to close levels of menus.
|
||||
NS_IMETHOD Escape(PRBool& aHandledFlag) = 0;
|
||||
|
@ -375,8 +375,10 @@ nsMenuBarFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFl
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
||||
{
|
||||
nsNavigationDirection theDirection;
|
||||
NS_DIRECTION_FROM_KEY_CODE(theDirection, aKeyCode);
|
||||
if (!mCurrentMenu)
|
||||
return NS_OK;
|
||||
|
||||
@ -389,17 +391,17 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
|
||||
if (isOpen) {
|
||||
// Let the child menu try to handle it.
|
||||
mCurrentMenu->KeyboardNavigation(aDirection, aHandledFlag);
|
||||
mCurrentMenu->KeyboardNavigation(aKeyCode, aHandledFlag);
|
||||
}
|
||||
|
||||
if (aHandledFlag)
|
||||
return NS_OK;
|
||||
|
||||
if (aDirection == NS_VK_RIGHT || aDirection == NS_VK_LEFT) {
|
||||
if NS_DIRECTION_IS_INLINE(theDirection) {
|
||||
|
||||
nsIMenuFrame* nextItem;
|
||||
|
||||
if (aDirection == NS_VK_RIGHT)
|
||||
if (theDirection == eNavigationDirection_End)
|
||||
GetNextMenuItem(mCurrentMenu, &nextItem);
|
||||
else GetPreviousMenuItem(mCurrentMenu, &nextItem);
|
||||
|
||||
@ -413,7 +415,7 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (aDirection == NS_VK_UP || aDirection == NS_VK_DOWN) {
|
||||
else if NS_DIRECTION_IS_BLOCK(theDirection) {
|
||||
// Open the menu and select its first item.
|
||||
mCurrentMenu->OpenMenu(PR_TRUE);
|
||||
mCurrentMenu->SelectFirstItem();
|
||||
|
@ -111,7 +111,7 @@ public:
|
||||
void ToggleMenuActiveState();
|
||||
|
||||
// Used to move up, down, left, and right in menus.
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag);
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag);
|
||||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag);
|
||||
// Called when the ESC key is held down to close levels of menus.
|
||||
NS_IMETHOD Escape(PRBool& aHandledFlag);
|
||||
|
@ -1228,12 +1228,12 @@ nsMenuFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
nsMenuFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
||||
{
|
||||
nsIFrame* frame = mPopupFrames.FirstChild();
|
||||
if (frame) {
|
||||
nsMenuPopupFrame* popup = (nsMenuPopupFrame*)frame;
|
||||
popup->KeyboardNavigation(aDirection, aHandledFlag);
|
||||
popup->KeyboardNavigation(aKeyCode, aHandledFlag);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -156,7 +156,7 @@ public:
|
||||
NS_IMETHOD Escape(PRBool& aHandledFlag);
|
||||
NS_IMETHOD Enter();
|
||||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag);
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag);
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag);
|
||||
|
||||
NS_IMETHOD SetParent(const nsIFrame* aParent);
|
||||
|
||||
|
@ -1751,15 +1751,18 @@ nsMenuPopupFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandled
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuPopupFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
||||
{
|
||||
nsNavigationDirection theDirection;
|
||||
NS_DIRECTION_FROM_KEY_CODE(theDirection, aKeyCode);
|
||||
|
||||
mIncrementalString = NS_LITERAL_STRING("");
|
||||
|
||||
// This method only gets called if we're open.
|
||||
if (!mCurrentMenu && (aDirection == NS_VK_RIGHT || aDirection == NS_VK_LEFT)) {
|
||||
if (!mCurrentMenu && NS_DIRECTION_IS_INLINE(theDirection)) {
|
||||
// We've been opened, but we haven't had anything selected.
|
||||
// We can handle RIGHT, but our parent handles LEFT.
|
||||
if (aDirection == NS_VK_RIGHT) {
|
||||
// We can handle End, but our parent handles Start.
|
||||
if (theDirection == eNavigationDirection_End) {
|
||||
nsIMenuFrame* nextItem;
|
||||
GetNextMenuItem(nsnull, &nextItem);
|
||||
if (nextItem) {
|
||||
@ -1780,9 +1783,10 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
|
||||
if (isOpen) {
|
||||
// Give our child a shot.
|
||||
mCurrentMenu->KeyboardNavigation(aDirection, aHandledFlag);
|
||||
mCurrentMenu->KeyboardNavigation(aKeyCode, aHandledFlag);
|
||||
}
|
||||
else if (aDirection == NS_VK_RIGHT && isContainer && !isDisabled) {
|
||||
else if (theDirection == eNavigationDirection_End &&
|
||||
isContainer && !isDisabled) {
|
||||
// The menu is not yet open. Open it and select the first item.
|
||||
aHandledFlag = PR_TRUE;
|
||||
mCurrentMenu->OpenMenu(PR_TRUE);
|
||||
@ -1793,17 +1797,17 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
if (aHandledFlag)
|
||||
return NS_OK; // The child menu took it for us.
|
||||
|
||||
// For the vertical direction, we can move up or down.
|
||||
if (aDirection == NS_VK_UP || aDirection == NS_VK_DOWN ||
|
||||
aDirection == NS_VK_HOME || aDirection == NS_VK_END) {
|
||||
// For block progression, we can move in either direction
|
||||
if (NS_DIRECTION_IS_BLOCK(theDirection) ||
|
||||
NS_DIRECTION_IS_BLOCK_TO_EDGE(theDirection)) {
|
||||
|
||||
nsIMenuFrame* nextItem;
|
||||
|
||||
if (aDirection == NS_VK_UP)
|
||||
if (theDirection == eNavigationDirection_Before)
|
||||
GetPreviousMenuItem(mCurrentMenu, &nextItem);
|
||||
else if (aDirection == NS_VK_DOWN)
|
||||
else if (theDirection == eNavigationDirection_After)
|
||||
GetNextMenuItem(mCurrentMenu, &nextItem);
|
||||
else if (aDirection == NS_VK_HOME)
|
||||
else if (theDirection == eNavigationDirection_First)
|
||||
GetNextMenuItem(nsnull, &nextItem);
|
||||
else
|
||||
GetPreviousMenuItem(nsnull, &nextItem);
|
||||
@ -1813,7 +1817,7 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
|
||||
aHandledFlag = PR_TRUE;
|
||||
}
|
||||
else if (mCurrentMenu && isContainer && isOpen) {
|
||||
if (aDirection == NS_VK_LEFT) {
|
||||
if (theDirection == eNavigationDirection_Start) {
|
||||
// Close it up.
|
||||
mCurrentMenu->OpenMenu(PR_FALSE);
|
||||
aHandledFlag = PR_TRUE;
|
||||
|
@ -145,7 +145,7 @@ public:
|
||||
const nsString& aPopupAlign,
|
||||
nsIFrame* aFrame, PRInt32 aXPos, PRInt32 aYPos);
|
||||
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag);
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag);
|
||||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag);
|
||||
|
||||
NS_IMETHOD Escape(PRBool& aHandledFlag);
|
||||
|
Loading…
Reference in New Issue
Block a user