mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-26 19:25:39 +00:00
Fix bug #4464: Missing autoscroll when selecting by mouse drag.
It's not very fast, but I guess that's a general problem with our scrolling. At least it works now, but it's not perfect. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34659 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
7f593196fc
commit
41cd987dc5
@ -37,6 +37,7 @@
|
|||||||
#include "LyXVC.h"
|
#include "LyXVC.h"
|
||||||
#include "qt_helpers.h"
|
#include "qt_helpers.h"
|
||||||
#include "Text.h"
|
#include "Text.h"
|
||||||
|
#include "TextMetrics.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include "graphics/GraphicsImage.h"
|
#include "graphics/GraphicsImage.h"
|
||||||
@ -224,8 +225,7 @@ private:
|
|||||||
// This is a 'heartbeat' generating synthetic mouse move events when the
|
// This is a 'heartbeat' generating synthetic mouse move events when the
|
||||||
// cursor is at the top or bottom edge of the viewport. One scroll per 0.2 s
|
// cursor is at the top or bottom edge of the viewport. One scroll per 0.2 s
|
||||||
SyntheticMouseEvent::SyntheticMouseEvent()
|
SyntheticMouseEvent::SyntheticMouseEvent()
|
||||||
: timeout(200), restart_timeout(true),
|
: timeout(200), restart_timeout(true)
|
||||||
x_old(-1), y_old(-1), min_scrollbar_old(-1), max_scrollbar_old(-1)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -770,18 +770,19 @@ void GuiWorkArea::mouseMoveEvent(QMouseEvent * e)
|
|||||||
e->accept();
|
e->accept();
|
||||||
|
|
||||||
// If we're above or below the work area...
|
// If we're above or below the work area...
|
||||||
if (e->y() <= 20 || e->y() >= viewport()->height() - 20) {
|
if ((e->y() <= 20 || e->y() >= viewport()->height() - 20)
|
||||||
|
&& e->buttons() == mouse_button::button1) {
|
||||||
// Make sure only a synthetic event can cause a page scroll,
|
// Make sure only a synthetic event can cause a page scroll,
|
||||||
// so they come at a steady rate:
|
// so they come at a steady rate:
|
||||||
if (e->y() <= 20)
|
if (e->y() <= 20)
|
||||||
// _Force_ a scroll up:
|
// _Force_ a scroll up:
|
||||||
cmd.set_y(-40);
|
cmd.set_y(e->y() - 21);
|
||||||
else
|
else
|
||||||
cmd.set_y(viewport()->height());
|
cmd.set_y(e->y() + 21);
|
||||||
// Store the event, to be handled when the timeout expires.
|
// Store the event, to be handled when the timeout expires.
|
||||||
synthetic_mouse_event_.cmd = cmd;
|
synthetic_mouse_event_.cmd = cmd;
|
||||||
|
|
||||||
if (synthetic_mouse_event_.timeout.running())
|
if (synthetic_mouse_event_.timeout.running()) {
|
||||||
// Discard the event. Note that it _may_ be handled
|
// Discard the event. Note that it _may_ be handled
|
||||||
// when the timeout expires if
|
// when the timeout expires if
|
||||||
// synthetic_mouse_event_.cmd has not been overwritten.
|
// synthetic_mouse_event_.cmd has not been overwritten.
|
||||||
@ -790,7 +791,8 @@ void GuiWorkArea::mouseMoveEvent(QMouseEvent * e)
|
|||||||
// occurred after the one used to start the timeout
|
// occurred after the one used to start the timeout
|
||||||
// in the first place.
|
// in the first place.
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
synthetic_mouse_event_.restart_timeout = true;
|
synthetic_mouse_event_.restart_timeout = true;
|
||||||
synthetic_mouse_event_.timeout.start();
|
synthetic_mouse_event_.timeout.start();
|
||||||
// Fall through to handle this event...
|
// Fall through to handle this event...
|
||||||
@ -806,24 +808,6 @@ void GuiWorkArea::mouseMoveEvent(QMouseEvent * e)
|
|||||||
synthetic_mouse_event_.restart_timeout = false;
|
synthetic_mouse_event_.restart_timeout = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has anything changed on-screen since the last QMouseEvent
|
|
||||||
// was received?
|
|
||||||
if (e->x() == synthetic_mouse_event_.x_old
|
|
||||||
&& e->y() == synthetic_mouse_event_.y_old
|
|
||||||
&& synthetic_mouse_event_.min_scrollbar_old == verticalScrollBar()->minimum()
|
|
||||||
&& synthetic_mouse_event_.max_scrollbar_old == verticalScrollBar()->maximum()) {
|
|
||||||
// Nothing changed on-screen since the last QMouseEvent.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Yes something has changed. Store the params used to check this.
|
|
||||||
synthetic_mouse_event_.x_old = e->x();
|
|
||||||
synthetic_mouse_event_.y_old = e->y();
|
|
||||||
synthetic_mouse_event_.min_scrollbar_old = verticalScrollBar()->minimum();
|
|
||||||
synthetic_mouse_event_.max_scrollbar_old = verticalScrollBar()->maximum();
|
|
||||||
|
|
||||||
// ... and dispatch the event to the LyX core.
|
|
||||||
dispatch(cmd);
|
dispatch(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,23 +847,81 @@ void GuiWorkArea::wheelEvent(QWheelEvent * ev)
|
|||||||
|
|
||||||
void GuiWorkArea::generateSyntheticMouseEvent()
|
void GuiWorkArea::generateSyntheticMouseEvent()
|
||||||
{
|
{
|
||||||
// Set things off to generate the _next_ 'pseudo' event.
|
int const e_y = synthetic_mouse_event_.cmd.y();
|
||||||
if (synthetic_mouse_event_.restart_timeout)
|
int const wh = buffer_view_->workHeight();
|
||||||
synthetic_mouse_event_.timeout.start();
|
bool const up = e_y < 0;
|
||||||
|
bool const down = e_y > wh;
|
||||||
|
|
||||||
// Has anything changed on-screen since the last timeout signal
|
// Set things off to generate the _next_ 'pseudo' event.
|
||||||
// was received?
|
int step = 50;
|
||||||
int const min_scrollbar = verticalScrollBar()->minimum();
|
if (synthetic_mouse_event_.restart_timeout) {
|
||||||
int const max_scrollbar = verticalScrollBar()->maximum();
|
// This is some magic formulae to determine the speed
|
||||||
if (min_scrollbar == synthetic_mouse_event_.min_scrollbar_old
|
// of scrolling related to the position of the mouse.
|
||||||
&& max_scrollbar == synthetic_mouse_event_.max_scrollbar_old) {
|
int time = 200;
|
||||||
|
if (up || down) {
|
||||||
|
int dist = up ? -e_y : e_y - wh;
|
||||||
|
time = max(min(200, 250000 / (dist * dist)), 1) ;
|
||||||
|
|
||||||
|
if (time < 40) {
|
||||||
|
step = 80000 / (time * time);
|
||||||
|
time = 40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
synthetic_mouse_event_.timeout.setTimeout(time);
|
||||||
|
synthetic_mouse_event_.timeout.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we scroll further ?
|
||||||
|
int const value = verticalScrollBar()->value();
|
||||||
|
if (value == verticalScrollBar()->maximum()
|
||||||
|
|| value == verticalScrollBar()->minimum()) {
|
||||||
|
synthetic_mouse_event_.timeout.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Yes it has. Store the params used to check this.
|
|
||||||
synthetic_mouse_event_.min_scrollbar_old = min_scrollbar;
|
// Scroll
|
||||||
synthetic_mouse_event_.max_scrollbar_old = max_scrollbar;
|
if (step <= 2 * wh) {
|
||||||
// ... and dispatch the event to the LyX core.
|
buffer_view_->scroll(up ? -step : step);
|
||||||
dispatch(synthetic_mouse_event_.cmd);
|
buffer_view_->updateMetrics();
|
||||||
|
} else {
|
||||||
|
buffer_view_->scrollDocView(value + up ? -step : step, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In which paragraph do we have to set the cursor ?
|
||||||
|
Cursor & cur = buffer_view_->cursor();
|
||||||
|
TextMetrics const & tm = buffer_view_->textMetrics(cur.text());
|
||||||
|
|
||||||
|
pair<pit_type, const ParagraphMetrics *> p = up ? tm.first() : tm.last();
|
||||||
|
ParagraphMetrics const & pm = *p.second;
|
||||||
|
pit_type const pit = p.first;
|
||||||
|
|
||||||
|
if (pm.rows().empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find the row at which we set the cursor.
|
||||||
|
RowList::const_iterator rit = pm.rows().begin();
|
||||||
|
RowList::const_iterator rlast = pm.rows().end();
|
||||||
|
int yy = pm.position() - pm.ascent();
|
||||||
|
for (--rlast; rit != rlast; ++rit) {
|
||||||
|
int h = rit->height();
|
||||||
|
if ((up && yy + h > 0)
|
||||||
|
|| (!up && yy + h > wh - defaultRowHeight()))
|
||||||
|
break;
|
||||||
|
yy += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the position of the cursor
|
||||||
|
bool bound;
|
||||||
|
int x = synthetic_mouse_event_.cmd.x();
|
||||||
|
pos_type const pos = rit->pos() + tm.getColumnNearX(pit, *rit, x, bound);
|
||||||
|
|
||||||
|
// Set the cursor
|
||||||
|
cur.pit() = pit;
|
||||||
|
cur.pos() = pos;
|
||||||
|
cur.boundary(bound);
|
||||||
|
|
||||||
|
buffer_view_->buffer().changed(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,10 +85,6 @@ public:
|
|||||||
FuncRequest cmd;
|
FuncRequest cmd;
|
||||||
Timeout timeout;
|
Timeout timeout;
|
||||||
bool restart_timeout;
|
bool restart_timeout;
|
||||||
int x_old;
|
|
||||||
int y_old;
|
|
||||||
int min_scrollbar_old;
|
|
||||||
int max_scrollbar_old;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user