Bug 1077515 - part 6 - Create a new nsISelectionController::PhysicalMove command. r=roc

This commit is contained in:
Jonathan Kew 2014-11-22 14:39:03 +00:00
parent 9fd75be794
commit 74d961eaf3
6 changed files with 138 additions and 1 deletions

View File

@ -16,7 +16,7 @@ interface nsIDOMNode;
interface nsISelection;
interface nsISelectionDisplay;
[scriptable, uuid(b1ff7faa-8097-431d-b7f1-b0615e3cd596)]
[scriptable, uuid(7835DE46-DB36-4BB7-8684-1049A0C13049)]
interface nsISelectionController : nsISelectionDisplay
{
const short SELECTION_NONE=0;
@ -143,6 +143,26 @@ interface nsISelectionController : nsISelectionDisplay
*/
void characterMove(in boolean forward, in boolean extend);
/** PhysicalMove will move the selection one "unit" in a given direction
* within the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
* the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aDirection
* @param aAmount character/line; word/lineBoundary
* @param aExtend should it collapse the selection of extend it?
*/
void physicalMove(in short direction, in short amount, in boolean extend);
/**
* nsFrameSelection::PhysicalMove depends on the ordering of these values;
* do not change without checking there!
*/
const short MOVE_LEFT = 0;
const short MOVE_RIGHT = 1;
const short MOVE_UP = 2;
const short MOVE_DOWN = 3;
/**
* CharacterExtendForDelete will extend the selection one character cell
* forward in the document.

View File

@ -227,6 +227,7 @@ public:
NS_IMETHOD GetCaretEnabled(bool *_retval);
NS_IMETHOD GetCaretVisible(bool *_retval);
NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility);
NS_IMETHOD PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend) MOZ_OVERRIDE;
NS_IMETHOD CharacterMove(bool aForward, bool aExtend);
NS_IMETHOD CharacterExtendForDelete();
NS_IMETHOD CharacterExtendForBackspace();
@ -445,6 +446,15 @@ nsTextInputSelectionImpl::SetCaretVisibilityDuringSelection(bool aVisibility)
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsTextInputSelectionImpl::PhysicalMove(int16_t aDirection, int16_t aAmount,
bool aExtend)
{
if (mFrameSelection)
return mFrameSelection->PhysicalMove(aDirection, aAmount, aExtend);
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsTextInputSelectionImpl::CharacterMove(bool aForward, bool aExtend)
{

View File

@ -2303,6 +2303,12 @@ NS_IMETHODIMP PresShell::GetSelectionFlags(int16_t *aOutEnable)
//implementation of nsISelectionController
NS_IMETHODIMP
PresShell::PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend)
{
return mSelection->PhysicalMove(aDirection, aAmount, aExtend);
}
NS_IMETHODIMP
PresShell::CharacterMove(bool aForward, bool aExtend)
{

View File

@ -249,6 +249,7 @@ public:
// nsISelectionController
NS_IMETHOD PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend) MOZ_OVERRIDE;
NS_IMETHOD CharacterMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
NS_IMETHOD CharacterExtendForDelete() MOZ_OVERRIDE;
NS_IMETHOD CharacterExtendForBackspace() MOZ_OVERRIDE;

View File

@ -415,6 +415,16 @@ public:
*/
virtual void UndefineCaretBidiLevel();
/** PhysicalMove will generally be called from the nsiselectioncontroller implementations.
* the effect being the selection will move one unit 'aAmount' in the
* given aDirection.
* @param aDirection the direction to move the selection
* @param aAmount amount of movement (char/line; word/page; eol/doc)
* @param aExtend continue selection
*/
/*unsafe*/
nsresult PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend);
/** CharacterMove will generally be called from the nsiselectioncontroller implementations.
* the effect being the selection will move one character left or right.
* @param aForward move forward in document.

View File

@ -1897,6 +1897,96 @@ nsFrameSelection::CommonPageMove(bool aForward,
offsets.offset, aExtend, false, CARET_ASSOCIATE_AFTER);
}
nsresult
nsFrameSelection::PhysicalMove(int16_t aDirection, int16_t aAmount,
bool aExtend)
{
NS_ENSURE_STATE(mShell);
// Flush out layout, since we need it to be up to date to do caret
// positioning.
mShell->FlushPendingNotifications(Flush_Layout);
if (!mShell) {
return NS_OK;
}
// Check that parameters are safe
if (aDirection < 0 || aDirection > 3 || aAmount < 0 || aAmount > 1) {
return NS_ERROR_FAILURE;
}
nsPresContext *context = mShell->GetPresContext();
if (!context) {
return NS_ERROR_FAILURE;
}
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
nsRefPtr<Selection> sel = mDomSelections[index];
if (!sel) {
return NS_ERROR_NULL_POINTER;
}
// Map the abstract movement amounts (0-1) to direction-specific
// selection units.
static const nsSelectionAmount inlineAmount[] =
{ eSelectCluster, eSelectWord };
static const nsSelectionAmount blockPrevAmount[] =
{ eSelectLine, eSelectBeginLine };
static const nsSelectionAmount blockNextAmount[] =
{ eSelectLine, eSelectEndLine };
struct PhysicalToLogicalMapping {
nsDirection direction;
const nsSelectionAmount *amounts;
};
static const PhysicalToLogicalMapping verticalLR[4] = {
{ eDirPrevious, blockPrevAmount }, // left
{ eDirNext, blockNextAmount }, // right
{ eDirPrevious, inlineAmount }, // up
{ eDirNext, inlineAmount } // down
};
static const PhysicalToLogicalMapping verticalRL[4] = {
{ eDirNext, blockNextAmount },
{ eDirPrevious, blockPrevAmount },
{ eDirPrevious, inlineAmount },
{ eDirNext, inlineAmount }
};
static const PhysicalToLogicalMapping horizontal[4] = {
{ eDirPrevious, inlineAmount },
{ eDirNext, inlineAmount },
{ eDirPrevious, blockPrevAmount },
{ eDirNext, blockNextAmount }
};
WritingMode wm;
nsIFrame *frame = nullptr;
int32_t offsetused = 0;
if (NS_SUCCEEDED(sel->GetPrimaryFrameForFocusNode(&frame, &offsetused,
true))) {
if (frame) {
wm = frame->GetWritingMode();
}
}
const PhysicalToLogicalMapping& mapping =
wm.IsVertical()
? wm.IsVerticalLR() ? verticalLR[aDirection] : verticalRL[aDirection]
: horizontal[aDirection];
nsresult rv = MoveCaret(mapping.direction, aExtend, mapping.amounts[aAmount],
eVisual);
if (NS_FAILED(rv)) {
// If we tried to do a line move, but couldn't move in the given direction,
// then we'll "promote" this to a line-edge move instead.
if (mapping.amounts[aAmount] == eSelectLine) {
rv = MoveCaret(mapping.direction, aExtend, mapping.amounts[aAmount + 1],
eVisual);
}
}
return rv;
}
nsresult
nsFrameSelection::CharacterMove(bool aForward, bool aExtend)
{