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.

> 
>>
>> Dimitri from Trolltech wrote on a similar problem:
>>
>> "You'll need to maintain flags, QTimers waiting N milliseconds and other
>> data to achive that. There's no equivalent information maintained by Qt."
>>
>> http://lists.trolltech.com/qt-interest/2006-02/thread00129-0.html
>>
>>
>> Hope this has convinced you. ;)
> 
> I trust you.

But the patch needs still more testing.

Peter
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 int id;
+       static bool locked;
+};
+
+// Qt doc: user event type between 1000 and 65535
+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 int id;
+       static bool locked;
+};
+
+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,30 @@
 }
 
 
-void GuiWorkArea::adjustViewWithScrollBar(int)
+void GuiWorkArea::lyxScrollEvent()
 {
        scrollBufferView(verticalScrollBar()->sliderPosition());
 }
 
 
+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 +457,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 +481,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())
@@ -436,6 +519,7 @@
        processKeySym(sym, q_key_state(e->modifiers()));
 }
 
+
 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();
 

Reply via email to