This patch sanitizes selection handling. Basically removes all InsetText special case selection-handling code and adjust the LyXText code a bit to handle also insets.
There are two remaining problems (selection related, but unrelated with the patch): - LFUN_MOUSE_RELEASE events get dispatched to the pointer position, and so when selecting inside an inset and finishing the selection with the pointer outside we get strange behaviour (for instance, if you finish over a button, the button dialog pops) - selections are not cleared out when the cursor gets out of an inset by clicking (I suppose that was done in insetUnlock or something). As a workaround, I've patched the painting code to not paint a selection if the cursor is not in that inset (trivial). It would remain to clear the selection when the cursor enters the inset: I've not done this because I don't know if this is the way to go. Comments? It would be also nice to hear about any selection-related regression apart mentioned problems. Alfredo 7 files changed, 52 insertions(+), 131 deletions(-)
Index: BufferView_pimpl.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.C,v retrieving revision 1.462 diff -u -p -u -r1.462 BufferView_pimpl.C --- BufferView_pimpl.C 13 Nov 2003 13:43:36 -0000 1.462 +++ BufferView_pimpl.C 13 Nov 2003 18:18:49 -0000 @@ -891,8 +891,26 @@ namespace { bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd) { switch (cmd.action) { + case LFUN_MOUSE_MOTION: { + FuncRequest cmd1(cmd, bv_); + UpdatableInset * inset = bv_->cursor().innerInset(); + DispatchResult res; + if (inset) { + cmd1.x -= inset->x(); + cmd1.y -= inset->y(); + res = inset->dispatch(cmd1); + } else + res = bv_->cursor().innerText()->dispatch(cmd1); + + if (bv_->fitCursor() || res.update()) { + bv_->update(); + bv_->cursor().updatePos(); + } + + return true; + } + case LFUN_MOUSE_PRESS: - case LFUN_MOUSE_MOTION: case LFUN_MOUSE_RELEASE: case LFUN_MOUSE_DOUBLE: case LFUN_MOUSE_TRIPLE: { Index: rowpainter.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/rowpainter.C,v retrieving revision 1.89 diff -u -p -u -r1.89 rowpainter.C --- rowpainter.C 13 Nov 2003 13:43:39 -0000 1.89 +++ rowpainter.C 13 Nov 2003 18:18:51 -0000 @@ -14,6 +14,7 @@ #include "rowpainter.h" #include "buffer.h" +#include "cursor.h" #include "debug.h" #include "bufferparams.h" #include "BufferView.h" @@ -945,7 +946,7 @@ void RowPainter::paint() paintBackground(); // paint the selection background - if (text_.selection.set()) + if (text_.selection.set() && &text_ == bv_.cursor().innerText()) paintSelection(); // vertical lines for appendix Index: text.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text.C,v retrieving revision 1.497 diff -u -p -u -r1.497 text.C --- text.C 13 Nov 2003 13:43:39 -0000 1.497 +++ text.C 13 Nov 2003 18:18:56 -0000 @@ -1467,7 +1467,7 @@ RowList::iterator LyXText::getRowNearY(int y, ParagraphList::iterator & pit) const { //lyxerr << "getRowNearY: y " << y << endl; -#if 1 +#if 0 ParagraphList::iterator const pend = boost::prior(ownerParagraphs().end()); pit = ownerParagraphs().begin(); Index: text3.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text3.C,v retrieving revision 1.179 diff -u -p -u -r1.179 text3.C --- text3.C 13 Nov 2003 13:43:41 -0000 1.179 +++ text3.C 13 Nov 2003 18:18:58 -0000 @@ -525,6 +525,7 @@ DispatchResult LyXText::dispatch(FuncReq switch (cmd.action) { case LFUN_APPENDIX: { + lyxerr << "<1>"; ParagraphList::iterator pit = cursorPar(); bool start = !pit->params().startOfAppendix(); @@ -1308,54 +1309,28 @@ DispatchResult LyXText::dispatch(FuncReq if (!bv->buffer()) break; - // Check for inset locking -#ifdef LOCK - if (bv->innerInset()) { - InsetOld * tli = bv->innerInset(); - LyXCursor cursor = bv->text->cursor; - LyXFont font = bv->text->getFont(bv->text->cursorPar(), cursor.pos()); - int width = tli->width(); - int inset_x = font.isVisibleRightToLeft() - ? cursor.x() - width : cursor.x(); - int start_x = inset_x + tli->scroll(); - FuncRequest cmd1 = cmd; - cmd1.x = cmd.x - start_x; - cmd1.y = cmd.y - cursor.y() + bv->top_y(); - tli->dispatch(cmd1); - break; - } -#endif - - // The test for not selection possible is needed, that only motion - // events are used, where the bottom press event was on - // the drawing area too + // The test for not selection possible is needed, that + // only motion events are used, where the bottom press + // event was on the drawing area too if (!selection_possible) { lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch: no selection possible\n"; break; } + RowList::iterator cursorrow = cursorRow(); + setCursorFromCoordinates(cmd.x, cmd.y + bv->top_y()); - RowList::iterator cursorrow = bv->text->cursorRow(); - bv->text->setCursorFromCoordinates(cmd.x, cmd.y + bv->top_y()); - #if 0 - // sorry for this but I have a strange error that the y value jumps at - // a certain point. This seems like an error in my xforms library or - // in some other local environment, but I would like to leave this here - // for the moment until I can remove this (Jug 20020418) - if (y_before < bv->text->cursor.y()) - lyxerr << y_before << ':' - << bv->text->cursor.y() << endl; - #endif // This is to allow jumping over large insets if (cursorrow == cursorRow()) { - if (cmd.y >= bv->workHeight()) + if (cursorrow != lastRow() + && cmd.y >= bv->workHeight()) { cursorDown(false); - else if (cmd.y < 0) + } else if (cursorrow != firstRow() + && cmd.y < 0) { cursorUp(false); + } } - - bv->text->setSelection(); -// bv->update(); + setSelection(); break; } @@ -1387,24 +1362,22 @@ DispatchResult LyXText::dispatch(FuncReq paste_internally = true; } - int const screen_first = bv->top_y(); + int const topy = bv->top_y(); selection_possible = true; // Clear the selection - bv->text->clearSelection(); - bv->update(); - bv->updateScrollbar(); - + clearSelection(); + // Right click on a footnote flag opens float menu if (cmd.button() == mouse_button::button3) { selection_possible = false; break; } - bv->text->setCursorFromCoordinates(cmd.x, cmd.y + screen_first); + setCursorFromCoordinates(cmd.x, cmd.y + topy); + selection.cursor = cursor; finishUndo(); - bv->text->selection.cursor = bv->text->cursor; - bv->x_target(bv->text->cursor.x()); + bv->x_target(cursor.x()); if (bv->fitCursor()) selection_possible = false; @@ -1432,7 +1405,7 @@ DispatchResult LyXText::dispatch(FuncReq return DispatchResult(true, false); selection_possible = false; - + if (cmd.button() == mouse_button::button2) break; Index: insets/insetcollapsable.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insetcollapsable.C,v retrieving revision 1.208 diff -u -p -u -r1.208 insetcollapsable.C --- insets/insetcollapsable.C 13 Nov 2003 13:43:42 -0000 1.208 +++ insets/insetcollapsable.C 13 Nov 2003 18:19:01 -0000 @@ -299,9 +299,9 @@ InsetCollapsable::priv_dispatch(FuncRequ return DispatchResult(true, true); case LFUN_MOUSE_MOTION: - if (!collapsed_ && cmd.y > button_dim.y2) - inset.dispatch(adjustCommand(cmd)); - return DispatchResult(true, true); + if (!collapsed_) + return inset.dispatch(adjustCommand(cmd)); + return DispatchResult(true, false); case LFUN_MOUSE_RELEASE: if (!collapsed_ && cmd.y > button_dim.y2) Index: insets/insettext.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insettext.C,v retrieving revision 1.541 diff -u -p -u -r1.541 insettext.C --- insets/insettext.C 13 Nov 2003 13:43:44 -0000 1.541 +++ insets/insettext.C 13 Nov 2003 18:19:02 -0000 @@ -114,11 +114,8 @@ void InsetText::init() for (; pit != end; ++pit) pit->setInsetOwner(this); text_.paragraphs_ = ¶graphs; - no_selection = true; old_par = -1; in_insetAllowed = false; - mouse_x = 0; - mouse_y = 0; } @@ -320,49 +317,6 @@ void InsetText::sanitizeEmptyText(Buffer extern LCursor theTempCursor; -void InsetText::lfunMousePress(FuncRequest const & cmd) -{ - lyxerr << "InsetText::lfunMousePress, inset: " << this << endl; - no_selection = true; - - // use this to check mouse motion for selection - mouse_x = cmd.x; - mouse_y = cmd.y; - - BufferView * bv = cmd.view(); - no_selection = false; - text_.clearSelection(); - - // set global cursor - bv->cursor() = theTempCursor; - lyxerr << "new global cursor: \n" << bv->cursor() << endl; - text_.setCursorFromCoordinates(cmd.x, cmd.y); -} - - -void InsetText::lfunMouseMotion(FuncRequest const & cmd) -{ - lyxerr << "InsetText::lfunMouseMotion, inset: " << this << endl; - if (no_selection || (mouse_x == cmd.x && mouse_y == cmd.y)) - return; - - BufferView * bv = cmd.view(); - LyXCursor cur = text_.cursor; - text_.setCursorFromCoordinates(cmd.x, cmd.y + dim_.asc); - bv->x_target(text_.cursor.x()); - if (cur != text_.cursor) { - text_.setSelection(); - updateLocal(bv, false); - } -} - - -void InsetText::lfunMouseRelease(FuncRequest const &) -{ - lyxerr << "InsetText::lfunMouseRelease, inset: " << this << endl; - no_selection = true; -} - void InsetText::edit(BufferView * bv, bool left) { @@ -410,27 +364,12 @@ DispatchResult InsetText::priv_dispatch( result.dispatched(true); bool was_empty = paragraphs.begin()->empty() && paragraphs.size() == 1; - if (cmd.action != LFUN_MOUSE_PRESS - && cmd.action != LFUN_MOUSE_MOTION - && cmd.action != LFUN_MOUSE_RELEASE) - no_selection = false; switch (cmd.action) { case LFUN_MOUSE_PRESS: - lfunMousePress(cmd); - result = DispatchResult(true, true); - break; - - case LFUN_MOUSE_MOTION: - lfunMouseMotion(cmd); - result = DispatchResult(true, true); - break; - - case LFUN_MOUSE_RELEASE: - lfunMouseRelease(cmd); - result = DispatchResult(true, true); + cmd.view()->cursor() = theTempCursor; + result = text_.dispatch(cmd); break; - case LFUN_SELFINSERT: if (bv->buffer()->isReadonly()) { // setErrorMessage(N_("Document is read only")); @@ -626,8 +565,9 @@ DispatchResult InsetText::priv_dispatch( break; } - /// If the action has deleted all text in the inset, we need to change the - // language to the language of the surronding text. + // If the action has deleted all text in the inset, we need + // to change the language to the language of the surronding + // text. if (!was_empty && paragraphs.begin()->empty() && paragraphs.size() == 1) { LyXFont font(LyXFont::ALL_IGNORE); Index: insets/insettext.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insettext.h,v retrieving revision 1.229 diff -u -p -u -r1.229 insettext.h --- insets/insettext.h 13 Nov 2003 13:43:44 -0000 1.229 +++ insets/insettext.h 13 Nov 2003 18:19:02 -0000 @@ -177,12 +177,6 @@ protected: private: /// void init(); - /// - void lfunMousePress(FuncRequest const &); - /// - void lfunMouseMotion(FuncRequest const &); - /// - void lfunMouseRelease(FuncRequest const &); // If the inset is empty set the language of the current font to the // language to the surronding text (if different). void sanitizeEmptyText(BufferView *); @@ -243,15 +237,10 @@ private: /// mutable lyx::paroffset_type old_par; - /// - // to remember old painted frame dimensions to clear it on the right spot! - /// + /** to remember old painted frame dimensions to clear it on + * the right spot! + */ mutable bool in_insetAllowed; - /// - // these are used to check for mouse movement in Motion selection code - /// - int mouse_x; - int mouse_y; public: /// mutable LyXText text_;