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:
smontagu%netscape.com 2002-08-06 23:47:01 +00:00
parent 2958cb7ad5
commit 8b17163212
8 changed files with 114 additions and 25 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);