Hello,
Between two chunk of work, I've managed to finish the patch, so here it is.
With this patch, when you click anywhere, including within nested text
insets (not for mathed), there is no redrawing at _all_. This is an
improvement over lyx-1.4 where the full screen were redrawn two times on
each mouse click.
I think this is a necessary improvement for Mac so, Jose, do you want it
for this alpha or shall I wait until it is released? I think I have
tested it enough already but I will understand if you'd like to wait. On
the other hand, this is the typical feature that needs a lot of testing
so the sooner users can test it, the better... you decide.
The next target for optimisation is mathed. Right now, any mouse click
or character typed inside a math inset will result in a full screen
redraw (this is the case also for 1.4). For Mac, this is prohibitive.
Then, I will try to investigate if we could use a pixmap cache. But this
last work will probably be for 1.6.
Abdel.
Index: BufferView.C
===================================================================
--- BufferView.C (revision 15915)
+++ BufferView.C (working copy)
@@ -362,15 +362,30 @@
// Update macro store
buffer_->buildMacros();
- // First drawing step
+ // Now do the first drawing step if needed. This consists on updating
+ // the CoordCache in updateMetrics().
+ // The second drawing step is done in WorkArea::redraw() if needed.
+
+ // Case when no explicit update is requested.
+ if (!(flags & (Update::SinglePar | Update::Force))) {
+ if (fitCursor() || multiParSel()) {
+ // a CoordCache update is needed
+ updateMetrics(false);
+ // tell the frontend to update the screen.
+ return true;
+ }
+ // no need to do anything.
+ return false;
+ }
+
+ // We are now in the case (Update::SinglePar | Update::Force)
updateMetrics(flags & Update::SinglePar);
- // The second drawing step is done in WorkArea::redraw() if needed.
- bool const need_second_step =
- (flags & (Update::SinglePar | Update::Force | Update::FitCursor
| Update::MultiParSel))
- && (fitCursor() || multiParSel());
+ // Don't forget to do check for fitCursor() and multiParSel().
+ fitCursor();
+ multiParSel();
- return need_second_step;
+ return true;
}
@@ -1063,7 +1078,7 @@
}
// When the above and the inner function are fixed, we can do this:
- //return needRedraw;
+ return needRedraw;
return true;
}
@@ -1217,7 +1232,7 @@
void BufferView::updateMetrics(bool singlepar)
{
// Clear out the position cache in case of full screen redraw.
- //if (!singlepar)
+ if (!singlepar)
coord_cache_.clear();
LyXText & buftext = buffer_->text();
Index: insets/insetcollapsable.C
===================================================================
--- insets/insetcollapsable.C (revision 15915)
+++ insets/insetcollapsable.C (working copy)
@@ -293,6 +293,11 @@
switch (cmd.action) {
case LFUN_MOUSE_PRESS:
+ if (cmd.button() == mouse_button::button1 && hitButton(cmd)) {
+ cur.dispatched();
+ cur.noUpdate();
+ break;
+ }
if (status() == Inlined)
InsetText::doDispatch(cur, cmd);
else if (status() == Open && !hitButton(cmd))
@@ -314,36 +319,35 @@
case LFUN_MOUSE_RELEASE:
if (cmd.button() == mouse_button::button3) {
+ // Open the Inset configuration dialog
showInsetDialog(&cur.bv());
break;
}
- switch (status()) {
-
- case Collapsed:
- //lyxerr << "InsetCollapsable::lfunMouseRelease 1" <<
endl;
- setStatus(cur, Open);
- edit(cur, true);
- cur.bv().cursor() = cur;
+ if (status() == Inlined) {
+ // The mouse click has to be within the inset!
+ InsetText::doDispatch(cur, cmd);
break;
+ }
- case Open: {
- if (hitButton(cmd)) {
- //lyxerr << "InsetCollapsable::lfunMouseRelease
2" << endl;
+ if (cmd.button() == mouse_button::button1 && hitButton(cmd)) {
+ // Left button is clicked, the user asks to toggle the
inset
+ // visual state.
+ cur.dispatched();
+ cur.updateFlags(Update::Force | Update::FitCursor);
+ if (status() == Collapsed) {
+ setStatus(cur, Open);
+ edit(cur, true);
+ }
+ else {
setStatus(cur, Collapsed);
- cur.bv().cursor() = cur;
- } else {
- //lyxerr << "InsetCollapsable::lfunMouseRelease
3" << endl;
- InsetText::doDispatch(cur, cmd);
}
+ cur.bv().cursor() = cur;
break;
}
- case Inlined:
- //lyxerr << "InsetCollapsable::lfunMouseRelease 4" <<
endl;
- InsetText::doDispatch(cur, cmd);
- break;
- }
+ // The mouse click is within the opened inset.
+ InsetText::doDispatch(cur, cmd);
break;
case LFUN_INSET_TOGGLE:
Index: lyxtext.h
===================================================================
--- lyxtext.h (revision 15915)
+++ lyxtext.h (working copy)
@@ -96,7 +96,9 @@
/// Set font over selection paragraphs and rebreak.
void setFont(LCursor & cur, LyXFont const &, bool toggleall = false);
- /// rebreaks the given par
+ /// Rebreaks the given paragraph.
+ /// \retval true if a full screen redraw is needed.
+ /// \retval false if a single paragraph redraw is enough.
bool redoParagraph(BufferView &, pit_type pit);
/// returns pos in given par at given x coord
Index: text.C
===================================================================
--- text.C (revision 15915)
+++ text.C (working copy)
@@ -1153,9 +1153,13 @@
// Because of the mix between the model (the paragraph contents) and the
// view (the paragraph breaking in rows, we have to do this here before
// the setCursor() call below.
- redoParagraph(cur.bv(), cpit);
- redoParagraph(cur.bv(), cpit + 1);
+ bool changed_height = redoParagraph(cur.bv(), cpit);
+ changed_height |= redoParagraph(cur.bv(), cpit + 1);
+ if (changed_height)
+ // A singlePar update is not enough in this case.
+ cur.updateFlags(Update::Force);
+
// This check is necessary. Otherwise the new empty paragraph will
// be deleted automatically. And it is more friendly for the user!
if (cur.pos() != 0 || isempty)
@@ -1253,7 +1257,9 @@
// FIXME: Inserting a character has nothing to do with setting a cursor.
// Because of the mix between the model (the paragraph contents) and the
// view (the paragraph breaking in rows, we have to do this here.
- redoParagraph(cur.bv(), cur.pit());
+ if (redoParagraph(cur.bv(), cur.pit()))
+ // A singlePar update is not enough in this case.
+ cur.updateFlags(Update::Force);
setCursor(cur, cur.pit(), cur.pos() + 1, false, cur.boundary());
charInserted();
}
@@ -1671,13 +1677,16 @@
} else
needsUpdate = dissolveInset(cur);
- // Make sure the cursor is correct. Is this really needed?
// FIXME: Inserting characters has nothing to do with setting a cursor.
// Because of the mix between the model (the paragraph contents)
// and the view (the paragraph breaking in rows, we have to do this
// here before the setCursorIntern() call.
if (needsUpdate) {
- redoParagraph(cur.bv(), cur.pit());
+ if (redoParagraph(cur.bv(), cur.pit()))
+ // A singlePar update is not enough in this case.
+ cur.updateFlags(Update::Force);
+ // Make sure the cursor is correct. Is this really needed?
+ // No, not really... at least not here!
setCursorIntern(cur, cur.pit(), cur.pos());
}
@@ -1786,7 +1795,9 @@
// Because of the mix between the model (the paragraph contents)
// and the view (the paragraph breaking in rows, we have to do this
// here before the setCursor() call.
- redoParagraph(cur.bv(), cur.pit());
+ if (redoParagraph(cur.bv(), cur.pit()))
+ // A singlePar update is not enough in this case.
+ cur.updateFlags(Update::Force);
setCursor(cur, cur.pit(), cur.pos(), false, cur.boundary());
return needsUpdate;
@@ -1929,7 +1940,7 @@
dim.asc += par.rows()[0].ascent();
dim.des -= par.rows()[0].ascent();
- bool const same = dim == par.dim();
+ bool const same = dim.height() == par.dim().height();
par.dim() = dim;
//lyxerr << "redoParagraph: " << par.rows().size() << " rows\n";
Index: text3.C
===================================================================
--- text3.C (revision 15915)
+++ text3.C (working copy)
@@ -305,6 +305,11 @@
{
lyxerr[Debug::ACTION] << "LyXText::dispatch: cmd: " << cmd << endl;
+ // FIXME: We use the update flag to indicates wether a singlePar or a
+ // full screen update is needed. We reset it here but shall we restore
it
+ // at the end?
+ cur.noUpdate();
+
BOOST_ASSERT(cur.text() == this);
BufferView * bv = &cur.bv();
CursorSlice oldTopSlice = cur.top();
@@ -997,6 +1002,11 @@
lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph"));
}
+ if (cmd.button() == mouse_button::button1) {
+ needsUpdate = false;
+ cur.noUpdate();
+ }
+
break;
}
@@ -1046,8 +1056,14 @@
break;
// finish selection
- if (cmd.button() == mouse_button::button1)
- theSelection().haveSelection(cur.selection());
+ if (cmd.button() == mouse_button::button1) {
+ if (cur.selection())
+ theSelection().haveSelection(cur.selection());
+ else {
+ needsUpdate = false;
+ cur.noUpdate();
+ }
+ }
bv->switchKeyMap();
break;
@@ -1483,6 +1499,19 @@
}
needsUpdate |= (cur.pos() != cur.lastpos()) && cur.selection();
+
+ // FIXME: The cursor flag is reset two lines below
+ // so we need to check here if some of the LFUN did touch that.
+ // for now only LyXText::erase() and LyXText::backspace() do that.
+ // The plan is to verify all the LFUNs and then to remove this
+ // singleParUpdate boolean altogether.
+ if (cur.result().update() & Update::Force) {
+ singleParUpdate = false;
+ needsUpdate = true;
+ }
+
+ // FIXME: the following code should go in favor of fine grained
+ // update flag treatment.
if (singleParUpdate)
// Inserting characters does not change par height
if (cur.bottom().paragraph().dim().height()
@@ -1494,10 +1523,11 @@
return;
} else
needsUpdate = true;
+
if (!needsUpdate
&& &oldTopSlice.inset() == &cur.inset()
&& oldTopSlice.idx() == cur.idx()
- && !sel
+ && !sel // sel is a backup of cur.selection() at the biginning of
the function.
&& !cur.selection())
cur.noUpdate();
else