Angus Leeming wrote:
>> On Montag, 1. Dezember 2003 11:21, Angus Leeming wrote:
>>> The patch has the timout returning after 400ms. Could you modify
>>> the code to return after 200ms and see how that feels please.
>> 
>> I would, but the patch is not applying anymore to cvs. I am at work
>> now, and don't have the sources from yesterday.
>> 
>> - From what I remember, even the 400 ms was fast ...
>> I just managed to follow the selections, so I was not unhappy with
>> that value.
> 
> Try 3, Kornel.
> 
> This one should feel much smoother when you move the mouse back into
> the work area. In fact, I thnk that this is ready to go into the
> sources (and, indeed, be ported to 1.3.x) but I'd value it if you
> road-tested it for me one more time.

Actually, try this. Factually the same but the debug output is gone, 
the comments reflect reality and it'll actually apply against current 
cvs ;-)

-- 
Angus
Index: src/frontends/qt2/QContentPane.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QContentPane.C,v
retrieving revision 1.29
diff -u -p -r1.29 QContentPane.C
--- src/frontends/qt2/QContentPane.C	1 Dec 2003 23:04:36 -0000	1.29
+++ src/frontends/qt2/QContentPane.C	1 Dec 2003 23:08:35 -0000
@@ -10,6 +10,8 @@
 
 #include <config.h>
 
+#include <boost/bind.hpp>
+
 #include "QWorkArea.h"
 #include "QContentPane.h"
 #include "QLyXKeySym.h"
@@ -18,9 +20,6 @@
 #include <qtimer.h>
 #include <qapplication.h>
 
-#include "funcrequest.h"
-
-
 namespace {
 
 /// return the LyX key state from Qt's
@@ -74,10 +73,20 @@ mouse_button::state q_motion_state(Qt::B
 } // namespace anon
 
 
+SyntheticMouseEvent::SyntheticMouseEvent()
+	: timeout(400), restart_timeout(true),
+	  x_old(-1), y_old(-1), scrollbar_value_old(-1.0)
+{}
+
+
 QContentPane::QContentPane(QWorkArea * parent)
 	: QWidget(parent, "content_pane", WRepaintNoErase),
 	  track_scrollbar_(true), wa_(parent)
 {
+	synthetic_mouse_event_.timeout.timeout.connect(
+		boost::bind(&QContentPane::generateSyntheticMouseEvent,
+			    this));
+
 	setFocusPolicy(QWidget::WheelFocus);
 	setFocus();
 	setCursor(ibeamCursor);
@@ -85,7 +94,25 @@ QContentPane::QContentPane(QWorkArea * p
 	// stupid moc strikes again
 	connect(wa_->scrollbar_, SIGNAL(valueChanged(int)),
 		this, SLOT(scrollBarChanged(int)));
+}
+
 
+void QContentPane::generateSyntheticMouseEvent()
+{
+	// Set things off to generate the _next_ 'psuedo' event.
+	if (synthetic_mouse_event_.restart_timeout)
+		synthetic_mouse_event_.timeout.start();
+
+	// Has anything changed on-screen since the last timeout signal
+	// was received?
+	double const scrollbar_value = wa_->scrollbar_->value();
+	if (scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) {
+		// Yes it has. Store the params used to check this.
+		synthetic_mouse_event_.scrollbar_value_old = scrollbar_value;
+
+		// ... and dispatch the event to the LyX core.
+		wa_->dispatch(synthetic_mouse_event_.cmd);
+	}
 }
 
 
@@ -115,6 +142,9 @@ void QContentPane::mousePressEvent(QMous
 
 void QContentPane::mouseReleaseEvent(QMouseEvent * e)
 {
+	if (synthetic_mouse_event_.timeout.running())
+		synthetic_mouse_event_.timeout.stop();
+
 	FuncRequest const cmd(LFUN_MOUSE_RELEASE, e->x(), e->y(),
 			      q_button_state(e->button()));
 	wa_->dispatch(cmd);
@@ -125,7 +155,50 @@ void QContentPane::mouseMoveEvent(QMouse
 {
 	FuncRequest const cmd(LFUN_MOUSE_MOTION, e->x(), e->y(),
 			      q_motion_state(e->state()));
-	wa_->dispatch(cmd);
+
+	// If we're above or below the work area...
+	if (e->y() <= 0 || e->y() >= height()) {
+		// Store the event, to be handled when the timeout expires.
+		synthetic_mouse_event_.cmd = cmd;
+
+		if (synthetic_mouse_event_.timeout.running())
+			// Wait for the timeout to expire before handling the
+			// event.
+			// Ie, when the timeout expires, we handle the
+			// most recent event but discard all others that
+			// occurred after the one used to start the timeout
+			// in the first place.
+			return;
+		else {
+			synthetic_mouse_event_.restart_timeout = true;
+			synthetic_mouse_event_.timeout.start();
+			// Fall through to handle this event...
+		}
+
+	} else if (synthetic_mouse_event_.timeout.running()) {
+		// Store the event, to be handled when the timeout expires.
+		// Thereafter, normal control is returned to mouseMoveEvent.
+		// This results in a much smoother 'feel' when moving the
+		// mouse back into the work area.
+		synthetic_mouse_event_.cmd = cmd;
+		synthetic_mouse_event_.restart_timeout = false;
+		return;
+	}
+
+	// Has anything changed on-screen since the last QMouseEvent
+	// was received?
+	double const scrollbar_value = wa_->scrollbar_->value();
+	if (e->x() != synthetic_mouse_event_.x_old ||
+	    e->y() != synthetic_mouse_event_.y_old ||
+	    scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) {
+		// Yes it has. Store the params used to check this.
+		synthetic_mouse_event_.x_old = e->x();
+		synthetic_mouse_event_.y_old = e->y();
+		synthetic_mouse_event_.scrollbar_value_old = scrollbar_value;
+
+		// ... and dispatch the event to the LyX core.
+		wa_->dispatch(cmd);
+	}
 }
 
 
@@ -200,4 +273,3 @@ void QContentPane::trackScrollbar(bool t
 {
 	track_scrollbar_ = track_on;
 }
-
Index: src/frontends/qt2/QContentPane.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/QContentPane.h,v
retrieving revision 1.12
diff -u -p -r1.12 QContentPane.h
--- src/frontends/qt2/QContentPane.h	30 Nov 2003 18:26:41 -0000	1.12
+++ src/frontends/qt2/QContentPane.h	1 Dec 2003 23:08:36 -0000
@@ -12,6 +12,13 @@
 #ifndef QCONTENTPANE_H
 #define QCONTENTPANE_H
 
+#ifdef emit
+#undef emit
+#endif
+
+#include "funcrequest.h"
+#include "frontends/Timeout.h"
+
 #include <qwidget.h>
 #include <qpixmap.h>
 
@@ -40,6 +47,27 @@ struct double_click {
 };
 
 
+/** Qt only emits mouse events when the mouse is being moved, but
+ *  we want to generate 'psuedo' mouse events when the mouse button is
+ *  pressed and the mouse cursor is below the bottom, or above the top
+ *  of the work area. In this way, we'll be able to continue scrolling
+ *  (and selecting) the text.
+ *
+ *  This struct stores all the parameters needed to make this happen.
+ */
+struct SyntheticMouseEvent
+{
+	SyntheticMouseEvent();
+
+	FuncRequest cmd;
+	Timeout timeout;
+	bool restart_timeout;
+	int x_old;
+	int y_old;
+	double scrollbar_value_old;
+};
+
+
 /**
  * Widget for actually drawing the document on
  */
@@ -76,6 +104,10 @@ public slots:
 
 	void scrollBarChanged(int);
 private:
+	/// The slot connected to SyntheticMouseEvent::timeout.
+	void generateSyntheticMouseEvent();
+	SyntheticMouseEvent synthetic_mouse_event_;
+
 	///
 	bool track_scrollbar_;
 	/// owning widget

Reply via email to