Peter Kümmel wrote:
Helge Hafting wrote:
Peter Kümmel wrote:
Abdelrazak Younes wrote:
Is this your only comment?
Yes. Sorry, don't have the time to do much more. I thought I'd share my
opinion ;-)
Sorry, too - for my harsh reply.
Anyway I don't think there is a simpler solution, at least I will
not look for it, this bug has cost me already too much time.
OK, I've found a better solution ;)
I had to test if it was worth to upgrade to 1GB ram.
I can understand that. I was thinking of collecting the scroll events
and cancelling them if a scroll operation is still on-going but maybe
that's what your patch do. I only briefly looked at it and it _seems_
very complicated.
Yes this is what it does. An it _is_ complicated. ;)
But I've found a more Qt like and elegant solution.
See attached patch, which should be much more readably.
I've introduced two events which are only posted once
to the event queue until the event is not processed.
This also improves(?) the scrolling under Windows,
see the comment in generateLyxScrollEvent.
I checked out todays SVN, applied this patch, and compiled.
Unfortunately, it doesn't help. At least not on linux.
Scrolling a maximized userguide may still overshoot by several pages.
Helge Hafting
I'm running out of ideas...
Is this patch better (the flush call is new)?
Or with processEvents instead of flush?
I replaced the two flush calls with processEvents. (Altered patch
attached if anyone else want to test it for improvement or regression)
This helped a lot in a short test!
Not entirely perfect, but much better when scrolling the
maximized userguide using the scrollbar. Instead of overshooting
by many pages, it often stopped when I wanted to, or sometimes
overshot by half a page.
Seems you're on the right track with this, and if we can get some
drawing optimizations as well then LyX 1.5 will be really good.
Unfortunately, I didn't get to test it with a loaded machine.
I did a "make install" and then a "make clean; make" in
order to test overshooting during a compile. But starting
exactly the same lyx binary after installation didn't work -
I got stupid messages about the userguide being in an
different version, and lyx2lyx failed! Creating a new
lyx document failed the same way, as lyx2lyx failed to convert the
default template too.
I guess a different version of lyx2lyx ran when I ran lyx from the
build directory instead of installing it. :-/
Helge Hafting
Index: src/frontends/qt4/GuiWorkArea.cpp
===================================================================
--- src/frontends/qt4/GuiWorkArea.cpp (revision 18430)
+++ src/frontends/qt4/GuiWorkArea.cpp (working copy)
@@ -190,8 +190,11 @@
// Initialize the vertical Scroll Bar
QObject::connect(verticalScrollBar(), SIGNAL(actionTriggered(int)),
- this, SLOT(adjustViewWithScrollBar(int)));
+ this, SLOT(generateLyxScrollEvent()));
+ QObject::connect(verticalScrollBar(), SIGNAL(sliderReleased()),
+ this, SLOT(lyxScrollEvent()));
+
// disable context menu for the scrollbar
verticalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu);
@@ -211,6 +214,53 @@
}
+
+class LyxScrollEvent : public QEvent
+{
+public:
+ LyxScrollEvent() : QEvent(QEvent::Type(id))
+ {}
+ static const int id;
+ static bool locked;
+};
+
+// Qt doc: user event type between 1000 and 65535
+const int LyxScrollEvent::id = 31415;
+bool LyxScrollEvent::locked = false;
+
+
+class LyxKeyEvent : public QKeyEvent
+{
+public:
+ LyxKeyEvent(QKeyEvent * e) :
+ QKeyEvent(QEvent::Type(id), e->key(),
+ e->modifiers(), e->text(), e->isAutoRepeat(), e->count())
+ {}
+ static const int id;
+ static bool locked;
+};
+
+const int LyxKeyEvent::id = 27182;
+bool LyxKeyEvent::locked = false;
+
+
+
+bool GuiWorkArea::event(QEvent * event)
+{
+ if (event->type() == LyxKeyEvent::id) {
+ lyxKeyEvent(dynamic_cast<LyxKeyEvent*>(event));
+ LyxKeyEvent::locked = false;
+ return true;
+ } else if (event->type() == LyxScrollEvent::id) {
+ lyxScrollEvent();
+ LyxScrollEvent::locked = false;
+ return true;
+ } else {
+ return QAbstractScrollArea::event(event);
+ }
+}
+
+
void GuiWorkArea::setScrollbarParams(int h, int scroll_pos, int scroll_line_step)
{
if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOn)
@@ -231,12 +281,31 @@
}
-void GuiWorkArea::adjustViewWithScrollBar(int)
+void GuiWorkArea::lyxScrollEvent()
{
scrollBufferView(verticalScrollBar()->sliderPosition());
+ QCoreApplication::processEvents();
}
+void GuiWorkArea::generateLyxScrollEvent()
+{
+ // This gives the old slow (the scroll bar couldn't follow the mouse)
+ // scrolling on Windows. Is it really better?
+ // Windows/Qt is here not as fast as X11
+ //lyxScrollEvent();return;
+
+ // multiple scroll events are merged into one
+ if (!LyxScrollEvent::locked) {
+ LyxScrollEvent::locked = true;
+ LyxScrollEvent* scrollEvent = new LyxScrollEvent;
+ QCoreApplication::postEvent(this, scrollEvent);
+ LYXERR(Debug::GUI) << "scrolling: one event posted" << endl;
+ } else {
+ LYXERR(Debug::GUI) << "scrolling: waiting for processing last scrolling event" << endl;
+ }
+}
+
void GuiWorkArea::dragEnterEvent(QDragEnterEvent * event)
{
if (event->mimeData()->hasUrls())
@@ -389,13 +458,14 @@
int const lines = qApp->wheelScrollLines() * e->delta() / 120;
verticalScrollBar()->setValue(verticalScrollBar()->value() -
lines * verticalScrollBar()->singleStep());
- adjustViewWithScrollBar();
+
+ generateLyxScrollEvent();
}
void GuiWorkArea::generateSyntheticMouseEvent()
{
-// Set things off to generate the _next_ 'pseudo' event.
+ // Set things off to generate the _next_ 'pseudo' event.
if (synthetic_mouse_event_.restart_timeout)
synthetic_mouse_event_.timeout.start();
@@ -412,18 +482,32 @@
}
+
void GuiWorkArea::keyPressEvent(QKeyEvent * e)
{
- // do nothing if there are other events
- // (the auto repeated events come too fast)
- if (e->isAutoRepeat() && QCoreApplication::hasPendingEvents()) {
- LYXERR(Debug::KEY)
- << BOOST_CURRENT_FUNCTION << endl
- << "key ignored" << endl;
- e->ignore();
- return;
+ // add here all keys which should be delayed
+ static const int delayed_keys = Qt::Key_PageDown | Qt::Key_PageUp;
+
+ if (e->key() & delayed_keys) {
+ if (!LyxKeyEvent::locked) {
+ LyxKeyEvent::locked = true;
+ QCoreApplication::postEvent(this, new LyxKeyEvent(e));
+ e->ignore();
+ LYXERR(Debug::GUI) << "key processing : event queued" << endl;
+ } else {
+ e->ignore();
+ LYXERR(Debug::GUI) << "key processing : waiting for event processing" << endl;
+ }
+ } else {
+ e->accept();
+ LyxKeyEvent lyxEvent(e);
+ lyxKeyEvent(&lyxEvent);
}
+}
+
+void GuiWorkArea::lyxKeyEvent(LyxKeyEvent * e)
+{
LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
<< " count=" << e->count()
<< " text=" << fromqstr(e->text())
@@ -434,8 +518,10 @@
boost::shared_ptr<QKeySymbol> sym(new QKeySymbol);
sym->set(e);
processKeySym(sym, q_key_state(e->modifiers()));
+ QCoreApplication::processEvents();
}
+
void GuiWorkArea::doubleClickTimeout() {
dc_event_.active = false;
}
Index: src/frontends/qt4/GuiWorkArea.h
===================================================================
--- src/frontends/qt4/GuiWorkArea.h (revision 18430)
+++ src/frontends/qt4/GuiWorkArea.h (working copy)
@@ -25,8 +25,6 @@
#include <QTimer>
#include <QPixmap>
-#include <queue>
-
class QWidget;
class QDragEnterEvent;
class QDropEvent;
@@ -38,6 +36,8 @@
class GuiView;
class QLPainter;
+class CursorWidget;
+class LyxKeyEvent;
/// for emulating triple click
class double_click {
@@ -81,7 +81,6 @@
* Qt-specific implementation of the work area
* (buffer view GUI)
*/
- class CursorWidget;
class GuiWorkArea : public QAbstractScrollArea, public WorkArea
{
Q_OBJECT
@@ -144,15 +143,16 @@
void inputMethodEvent(QInputMethodEvent * ev);
/// IM query
QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ /// overwrite QObject function
+ bool event(QEvent * event);
+ ///
+ void lyxKeyEvent(LyxKeyEvent * event);
-public Q_SLOTS:
+private Q_SLOTS:
/// Adjust the LyX buffer view with the position of the scrollbar.
- /**
- * The action argument is not used in the the code, it is there
- * only for the connection to the vertical srollbar signal which
- * emits an 'int' action.
- */
- void adjustViewWithScrollBar(int action = 0);
+ void lyxScrollEvent();
+ ///
+ void generateLyxScrollEvent();
/// timer to limit triple clicks
void doubleClickTimeout();