Bug 1077515 - part 7 - Support physical caret movement and selection commands in nsGlobalWindowCommands. r=roc

This commit is contained in:
Jonathan Kew 2014-11-22 14:39:04 +00:00
Родитель 74d961eaf3
Коммит 2476fc58fc
1 изменённых файлов: 215 добавлений и 53 удалений

Просмотреть файл

@ -83,6 +83,24 @@ const char * const sSelectPageDownString = "cmd_selectPageDown";
const char * const sSelectTopString = "cmd_selectTop";
const char * const sSelectBottomString = "cmd_selectBottom";
// Physical-direction movement and selection commands
const char * const sMoveLeftString = "cmd_moveLeft";
const char * const sMoveRightString = "cmd_moveRight";
const char * const sMoveUpString = "cmd_moveUp";
const char * const sMoveDownString = "cmd_moveDown";
const char * const sMoveLeft2String = "cmd_moveLeft2";
const char * const sMoveRight2String = "cmd_moveRight2";
const char * const sMoveUp2String = "cmd_moveUp2";
const char * const sMoveDown2String = "cmd_moveDown2";
const char * const sSelectLeftString = "cmd_selectLeft";
const char * const sSelectRightString = "cmd_selectRight";
const char * const sSelectUpString = "cmd_selectUp";
const char * const sSelectDownString = "cmd_selectDown";
const char * const sSelectLeft2String = "cmd_selectLeft2";
const char * const sSelectRight2String = "cmd_selectRight2";
const char * const sSelectUp2String = "cmd_selectUp2";
const char * const sSelectDown2String = "cmd_selectDown2";
#if 0
#pragma mark -
@ -116,6 +134,16 @@ public:
// no member variables, please, we're stateless!
};
// this class implements physical-movement versions of the above
class nsPhysicalSelectMoveScrollCommand : public nsSelectionCommandsBase
{
public:
NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandContext);
// no member variables, please, we're stateless!
};
// this class implements other selection commands
class nsSelectCommand : public nsSelectionCommandsBase
{
@ -126,6 +154,16 @@ public:
// no member variables, please, we're stateless!
};
// this class implements physical-movement versions of selection commands
class nsPhysicalSelectCommand : public nsSelectionCommandsBase
{
public:
NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandContext);
// no member variables, please, we're stateless!
};
#if 0
#pragma mark -
#endif
@ -194,6 +232,39 @@ nsSelectionCommandsBase::GetSelectionControllerFromWindow(nsPIDOMWindow *aWindow
#pragma mark -
#endif
// Helpers for nsSelectMoveScrollCommand and nsPhysicalSelectMoveScrollCommand
static void
AdjustFocusAfterCaretMove(nsPIDOMWindow* aWindow)
{
// adjust the focus to the new caret position
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIDOMElement> result;
fm->MoveFocus(aWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET,
nsIFocusManager::FLAG_NOSCROLL, getter_AddRefs(result));
}
}
static bool
IsCaretOnInWindow(nsPIDOMWindow* aWindow, nsISelectionController* aSelCont)
{
// We allow the caret to be moved with arrow keys on any window for which
// the caret is enabled. In particular, this includes caret-browsing mode
// in non-chrome documents.
bool caretOn = false;
aSelCont->GetCaretEnabled(&caretOn);
if (!caretOn) {
caretOn = Preferences::GetBool("accessibility.browsewithcaret");
if (caretOn) {
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
caretOn = false;
}
}
}
return caretOn;
}
static const struct BrowseCommand {
const char *reverse, *forward;
nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
@ -235,85 +306,158 @@ nsSelectMoveScrollCommand::DoCommand(const char *aCommandName, nsISupports *aCom
GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont));
NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);
// We allow the caret to be moved with arrow keys on any window for which
// the caret is enabled. In particular, this includes caret-browsing mode
// in non-chrome documents.
bool caretOn = false;
selCont->GetCaretEnabled(&caretOn);
if (!caretOn) {
caretOn = Preferences::GetBool("accessibility.browsewithcaret");
if (caretOn) {
nsCOMPtr<nsIDocShell> docShell = piWindow->GetDocShell();
if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
caretOn = false;
}
}
}
bool caretOn = IsCaretOnInWindow(piWindow, selCont);
for (size_t i = 0; i < ArrayLength(browseCommands); i++) {
bool forward = !strcmp(aCommandName, browseCommands[i].forward);
if (forward || !strcmp(aCommandName, browseCommands[i].reverse)) {
if (caretOn && browseCommands[i].move &&
NS_SUCCEEDED((selCont->*(browseCommands[i].move))(forward, false))) {
// adjust the focus to the new caret position
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIDOMElement> result;
fm->MoveFocus(piWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET,
nsIFocusManager::FLAG_NOSCROLL,
getter_AddRefs(result));
}
AdjustFocusAfterCaretMove(piWindow);
return NS_OK;
}
return (selCont->*(browseCommands[i].scroll))(forward);
}
}
return NS_ERROR_NOT_IMPLEMENTED;
}
#if 0
#pragma mark -
#endif
// XXX It's not clear to me yet how we should handle the "scroll" option
// for these commands; for now, I'm mapping them back to ScrollCharacter,
// ScrollLine, etc., as if for horizontal-mode content, but this may need
// to be reconsidered once we have more experience with vertical content.
static const struct PhysicalBrowseCommand {
const char *command;
int16_t direction, amount;
nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
} physicalBrowseCommands[] = {
{ sMoveLeftString, nsISelectionController::MOVE_LEFT, 0,
&nsISelectionController::ScrollCharacter },
{ sMoveRightString, nsISelectionController::MOVE_RIGHT, 0,
&nsISelectionController::ScrollCharacter },
{ sMoveUpString, nsISelectionController::MOVE_UP, 0,
&nsISelectionController::ScrollLine },
{ sMoveDownString, nsISelectionController::MOVE_DOWN, 0,
&nsISelectionController::ScrollLine },
{ sMoveLeft2String, nsISelectionController::MOVE_LEFT, 1,
&nsISelectionController::ScrollCharacter },
{ sMoveRight2String, nsISelectionController::MOVE_RIGHT, 1,
&nsISelectionController::ScrollCharacter },
{ sMoveUp2String, nsISelectionController::MOVE_UP, 1,
&nsISelectionController::CompleteScroll },
{ sMoveDown2String, nsISelectionController::MOVE_DOWN, 1,
&nsISelectionController::CompleteScroll },
};
nsresult
nsSelectCommand::DoCommand(const char *aCommandName, nsISupports *aCommandContext)
nsPhysicalSelectMoveScrollCommand::DoCommand(const char *aCommandName,
nsISupports *aCommandContext)
{
nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(aCommandContext));
nsCOMPtr<nsISelectionController> selCont;
GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont));
NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
bool caretOn = IsCaretOnInWindow(piWindow, selCont);
for (size_t i = 0; i < ArrayLength(physicalBrowseCommands); i++) {
const PhysicalBrowseCommand& cmd = physicalBrowseCommands[i];
if (!strcmp(aCommandName, cmd.command)) {
int16_t dir = cmd.direction;
if (caretOn &&
NS_SUCCEEDED(selCont->PhysicalMove(dir, cmd.amount, false))) {
AdjustFocusAfterCaretMove(piWindow);
return NS_OK;
}
bool forward = (dir == nsISelectionController::MOVE_RIGHT ||
dir == nsISelectionController::MOVE_DOWN);
return (selCont->*(cmd.scroll))(forward);
}
}
return NS_ERROR_NOT_IMPLEMENTED;
}
#if 0
#pragma mark -
#endif
static const struct SelectCommand {
const char *reverse, *forward;
nsresult (NS_STDCALL nsISelectionController::*select)(bool, bool);
} selectCommands[] = {
{ sSelectCharPreviousString, sSelectCharNextString,
&nsISelectionController::CharacterMove },
{ sSelectWordPreviousString, sSelectWordNextString,
&nsISelectionController::WordMove },
{ sSelectBeginLineString, sSelectEndLineString,
&nsISelectionController::IntraLineMove },
{ sSelectLinePreviousString, sSelectLineNextString,
&nsISelectionController::LineMove },
{ sSelectPageUpString, sSelectPageDownString,
&nsISelectionController::PageMove },
{ sSelectTopString, sSelectBottomString,
&nsISelectionController::CompleteMove }
};
nsresult
nsSelectCommand::DoCommand(const char *aCommandName,
nsISupports *aCommandContext)
{
nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(aCommandContext));
nsCOMPtr<nsISelectionController> selCont;
GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont));
NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);
// These commands are so the browser can use caret navigation key bindings -
// Helps with accessibility - aaronl@netscape.com
if (!nsCRT::strcmp(aCommandName, sSelectCharPreviousString))
rv = selCont->CharacterMove(false, true);
else if (!nsCRT::strcmp(aCommandName, sSelectCharNextString))
rv = selCont->CharacterMove(true, true);
else if (!nsCRT::strcmp(aCommandName, sSelectWordPreviousString))
rv = selCont->WordMove(false, true);
else if (!nsCRT::strcmp(aCommandName, sSelectWordNextString))
rv = selCont->WordMove(true, true);
else if (!nsCRT::strcmp(aCommandName, sSelectBeginLineString))
rv = selCont->IntraLineMove(false, true);
else if (!nsCRT::strcmp(aCommandName, sSelectEndLineString))
rv = selCont->IntraLineMove(true, true);
else if (!nsCRT::strcmp(aCommandName, sSelectLinePreviousString))
rv = selCont->LineMove(false, true);
else if (!nsCRT::strcmp(aCommandName, sSelectLineNextString))
rv = selCont->LineMove(true, true);
else if (!nsCRT::strcmp(aCommandName, sSelectPageUpString))
rv = selCont->PageMove(false, true);
else if (!nsCRT::strcmp(aCommandName, sSelectPageDownString))
rv = selCont->PageMove(true, true);
else if (!nsCRT::strcmp(aCommandName, sSelectTopString))
rv = selCont->CompleteMove(false, true);
else if (!nsCRT::strcmp(aCommandName, sSelectBottomString))
rv = selCont->CompleteMove(true, true);
for (size_t i = 0; i < ArrayLength(selectCommands); i++) {
bool forward = !strcmp(aCommandName, selectCommands[i].forward);
if (forward || !strcmp(aCommandName, selectCommands[i].reverse)) {
return (selCont->*(selectCommands[i].select))(forward, true);
}
}
return NS_ERROR_NOT_IMPLEMENTED;
}
return rv;
#if 0
#pragma mark -
#endif
static const struct PhysicalSelectCommand {
const char *command;
int16_t direction, amount;
} physicalSelectCommands[] = {
{ sSelectLeftString, nsISelectionController::MOVE_LEFT, 0 },
{ sSelectRightString, nsISelectionController::MOVE_RIGHT, 0 },
{ sSelectUpString, nsISelectionController::MOVE_UP, 0 },
{ sSelectDownString, nsISelectionController::MOVE_DOWN, 0 },
{ sSelectLeft2String, nsISelectionController::MOVE_LEFT, 1 },
{ sSelectRight2String, nsISelectionController::MOVE_RIGHT, 1 },
{ sSelectUp2String, nsISelectionController::MOVE_UP, 1 },
{ sSelectDown2String, nsISelectionController::MOVE_DOWN, 1 }
};
nsresult
nsPhysicalSelectCommand::DoCommand(const char *aCommandName,
nsISupports *aCommandContext)
{
nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(aCommandContext));
nsCOMPtr<nsISelectionController> selCont;
GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont));
NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);
for (size_t i = 0; i < ArrayLength(physicalSelectCommands); i++) {
if (!strcmp(aCommandName, physicalSelectCommands[i].command)) {
return selCont->PhysicalMove(physicalSelectCommands[i].direction,
physicalSelectCommands[i].amount,
true);
}
}
return NS_ERROR_NOT_IMPLEMENTED;
}
#if 0
@ -868,6 +1012,15 @@ nsWindowCommandRegistration::RegisterWindowCommands(
NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sCharPreviousString);
NS_REGISTER_LAST_COMMAND(nsSelectMoveScrollCommand, sCharNextString);
NS_REGISTER_FIRST_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveLeftString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveRightString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveUpString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveDownString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveLeft2String);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveRight2String);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveUp2String);
NS_REGISTER_LAST_COMMAND(nsPhysicalSelectMoveScrollCommand, sMoveDown2String);
NS_REGISTER_FIRST_COMMAND(nsSelectCommand, sSelectCharPreviousString);
NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectCharNextString);
NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectWordPreviousString);
@ -881,6 +1034,15 @@ nsWindowCommandRegistration::RegisterWindowCommands(
NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectTopString);
NS_REGISTER_LAST_COMMAND(nsSelectCommand, sSelectBottomString);
NS_REGISTER_FIRST_COMMAND(nsPhysicalSelectCommand, sSelectLeftString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectRightString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectUpString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectDownString);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectLeft2String);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectRight2String);
NS_REGISTER_NEXT_COMMAND(nsPhysicalSelectCommand, sSelectUp2String);
NS_REGISTER_LAST_COMMAND(nsPhysicalSelectCommand, sSelectDown2String);
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_cut");
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_copy");
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_paste");