Always remove selection after cursor up/down

When the cursor cannot move on cursor up/down, at least the selection
should be cleared (when not selecting).

To detect this, the method Cursor::upDownInText has been modified to
return true when cursor is at top/bottom of inset, but there is some
room above/below.

Moreover, introduce the functions LFUN_FINISHED_UP/DOWN, which is
dispatched at upper cursor level as long as no local movement is
possible. This allows to handle differently the original char moving
action and its consequences.

Fixes part of bug #12310.
This commit is contained in:
Jean-Marc Lasgouttes 2021-06-29 12:43:59 +02:00
parent 8d90bb9991
commit 008a0825e8
5 changed files with 53 additions and 14 deletions

View File

@ -2216,7 +2216,7 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded)
if (updateNeeded)
forceBufferUpdate();
}
return false;
return valid_destination;
}
// with and without selection are handled differently

View File

@ -496,8 +496,9 @@ public:
/// return true if fullscreen update is needed
bool down();
/// move up/down in a text inset, called for LFUN_UP/DOWN,
/// return true if successful, updateNeeded set to true if fullscreen
/// update is needed, otherwise it's not touched
/// return true if the cursor has moved or can move, updateNeeded
/// set to true if fullscreen update is needed, otherwise it's not
/// touched
bool upDownInText(bool up, bool & updateNeeded);
/// move up/down in math or any non text inset, call for LFUN_UP/DOWN
/// return true if successful

View File

@ -500,6 +500,8 @@ enum FuncCode
LFUN_SPELLING_ADD_LOCAL, // jspitzm 20210306
// 390
LFUN_SPELLING_REMOVE_LOCAL, // jspitzm 20210307
LFUN_FINISHED_DOWN, // lasgouttes 20210629
LFUN_FINISHED_UP, // lasgouttes 20210629
LFUN_LASTACTION // end of the table
};

View File

@ -1668,6 +1668,22 @@ void LyXAction::init()
*/
{ LFUN_FINISHED_RIGHT, "", ReadOnly, Hidden },
/*!
* \var lyx::FuncCode lyx::LFUN_FINISHED_UP
* \li Action: Moves the cursor out of the current slice, going up.
* \li Notion: See also #LFUN_FINISHED_DOWN.
* \endvar
*/
{ LFUN_FINISHED_UP, "", ReadOnly, Hidden },
/*!
* \var lyx::FuncCode lyx::LFUN_FINISHED_DOWN
* \li Action: Moves the cursor out of the current slice, going down.
* \li Notion: See also #LFUN_FINISHED_DOWN.
* \endvar
*/
{ LFUN_FINISHED_DOWN, "", ReadOnly, Hidden },
/*!
* \var lyx::FuncCode lyx::LFUN_FLEX_INSERT
* \li Action: Inserts CharStyle, Custom inset or XML short element.

View File

@ -892,14 +892,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
case LFUN_UP:
case LFUN_DOWN: {
// stop/start the selection
bool select = cmd.action() == LFUN_DOWN_SELECT ||
cmd.action() == LFUN_UP_SELECT;
bool const select = cmd.action() == LFUN_DOWN_SELECT
|| cmd.action() == LFUN_UP_SELECT;
// move cursor up/down
bool up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP;
bool const atFirstOrLastRow = cur.atFirstOrLastRow(up);
bool const up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP;
if (!atFirstOrLastRow) {
if (!cur.atFirstOrLastRow(up)) {
needsUpdate |= cur.selHandle(select);
cur.upDownInText(up, needsUpdate);
needsUpdate |= cur.beforeDispatchCursor().inMathed();
@ -915,13 +913,35 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
cur.forceBufferUpdate();
break;
}
needsUpdate |= cur.selHandle(select);
bool const can_move = cur.upDownInText(up, needsUpdate);
// if the cursor can be moved up or down at an upper level,
// delegate the dispatch to next level. Otherwise, we are
// done.
if (can_move) {
cmd = FuncRequest(up ? LFUN_FINISHED_UP : LFUN_FINISHED_DOWN);
cur.undispatched();
}
}
// if the cursor cannot be moved up or down do not remove
// the selection right now, but wait for the next dispatch.
if (select)
needsUpdate |= cur.selHandle(select);
break;
}
case LFUN_FINISHED_UP:
case LFUN_FINISHED_DOWN: {
// move cursor up/down
bool const up = cmd.action() == LFUN_FINISHED_UP;
if (!cur.atFirstOrLastRow(up)) {
cur.upDownInText(up, needsUpdate);
cur.undispatched();
needsUpdate |= cur.beforeDispatchCursor().inMathed();
} else {
bool const can_move = cur.upDownInText(up, needsUpdate);
// if the cursor can be moved up or down and we are not
// moving cusor at top level, wait for the next dispatch.
// Otherwise, we are done.
if (can_move)
cur.undispatched();
}
break;