Don't perform hit testing if we haven't painted the graphics window.
This change is quite subtle. The goal is to improve responsiveness of highlighting even further. To understand this change you need to keep in mind that Windows and Gtk have dramatically different behavior for paint (WM_PAINT in Windows, expose in Gtk) and mouse move events. In Windows, WM_PAINT and WM_MOUSEMOVE, unless sent explicitly, are synthesized: WM_MOUSEMOVE is delivered when there are no other messages and the current cursor position doesn't match the remembered one, and WM_PAINT is delivered when there are no other messages, even WM_MOUSEMOVE. This is pretty clever because it doesn't swamp programs that are slow to process either of those events with even more of them, ensuring they remain responsive. In Gtk, expose events are delivered at the end of the frame whenever there is an invalid view, and every single mouse move that happened will result in a separate event. If mouse move events are handled quickly, then the behavior is identical in either case: * process mouse move event * perform hit testing * invalidate view * no more events to process! * there are invalid views * repaint If, however, mouse move events are handled slower, then the behavior diverges. With Gtk: * process mouse move event * perform hit testing (slow) * while this happens, ten more mouse move events are added * invalidate view * end of frame! * there are invalid views * repaint * process mouse move event... As a result, the Gtk-hosted UI hopelessly lags behind user input. This is very irritating. With Windows: * process mouse move event * perform hit testing (slow) * while this happens, mouse was moved * invalidate view * process mouse move event... As a result, the Windows-hosted UI never repaints while the mouse is moved. This is also very irritating. Commit HEAD^ has fixed the problems with Gtk-based UI by making hit testing so fast that mouse move events never quite overflow the queue. There's still a barely noticeable lag but it's better. However, the problems with Windows remained because while the queue doesn't *overflow* with the faster hit testing code, it doesn't go *empty* either! Thus we still don't repaint. This commit builds on top of HEAD^ and makes it so that we don't actually hit test anything if we haven't painted the result of the previous hit test already. This fixes the problem on Windows but also helps Gtk a little bit. Curiously, the Cocoa-based UI never suffered from any of these problems. To my understanding (it's somewhat underdocumented), it processes mouse moves like Windows, but paints like Gtk.pull/4/head
parent
bda2835e9f
commit
6e56b00b9a
|
@ -383,7 +383,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
|
|
||||||
if(!s.Equals(&hover)) {
|
if(!s.Equals(&hover)) {
|
||||||
hover = s;
|
hover = s;
|
||||||
InvalidateGraphics();
|
PaintGraphics();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,14 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
// a point, mouse down (thus selecting it), and drag, in an
|
// a point, mouse down (thus selecting it), and drag, in an
|
||||||
// effort to drag the point, but instead hover a different
|
// effort to drag the point, but instead hover a different
|
||||||
// entity before we move far enough to start the drag.
|
// entity before we move far enough to start the drag.
|
||||||
if(!leftDown) HitTestMakeSelection(mp);
|
if(!leftDown) {
|
||||||
|
// Hit testing can potentially take a lot of time.
|
||||||
|
// If we haven't painted since last time we highlighted
|
||||||
|
// something, don't hit test again, since this just causes
|
||||||
|
// a lag.
|
||||||
|
if(!havePainted) return;
|
||||||
|
HitTestMakeSelection(mp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -261,6 +268,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
havePainted = false;
|
||||||
switch(pending.operation) {
|
switch(pending.operation) {
|
||||||
case DRAGGING_CONSTRAINT: {
|
case DRAGGING_CONSTRAINT: {
|
||||||
Constraint *c = SK.constraint.FindById(pending.constraint);
|
Constraint *c = SK.constraint.FindById(pending.constraint);
|
||||||
|
@ -449,7 +458,6 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
{
|
{
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
}
|
}
|
||||||
havePainted = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsWindow::ClearPending(void) {
|
void GraphicsWindow::ClearPending(void) {
|
||||||
|
|
Loading…
Reference in New Issue