Improve zooming with trackpad and scrollwheel

On macOS actual scroll delta is used for the zoom amount.
On Windows WHEEL_DELTA is used to allow smooth scrolling if supported.
Shift+Scroll is added for 10x finer zooming.
pull/854/head
Koen Schmeets 2020-11-23 22:11:14 +01:00 committed by phkahler
parent 681a50db26
commit 2939abf5f8
7 changed files with 34 additions and 19 deletions

View File

@ -113,6 +113,7 @@ Other new features:
that are shortcuts to the respective configuration screens.
* New cmake build options using -DENABLE_OPENMP=yes and -DENABLE_LTO=yes
to enable support for multi-threading and link-time optimization.
* "Shift+Scroll" for ten times finer zoom.
Bugs fixed:
* Fixed broken --view options for command line thumbnail image creation.

View File

@ -877,7 +877,6 @@ bool GraphicsWindow::ConstrainPointByHovered(hEntity pt, const Point2d *projecte
bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) {
using Platform::MouseEvent;
double width, height;
window->GetContentSize(&width, &height);
@ -918,7 +917,7 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) {
break;
case MouseEvent::Type::SCROLL_VERT:
this->MouseScroll(event.x, event.y, (int)event.scrollDelta);
this->MouseScroll(event.x, event.y, event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta);
break;
case MouseEvent::Type::LEAVE:
@ -1472,18 +1471,25 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
}
}
void GraphicsWindow::MouseScroll(double x, double y, int delta) {
void GraphicsWindow::MouseScroll(double x, double y, double delta) {
double offsetRight = offset.Dot(projRight);
double offsetUp = offset.Dot(projUp);
double righti = x/scale - offsetRight;
double upi = y/scale - offsetUp;
if(delta > 0) {
scale *= 1.2;
} else if(delta < 0) {
scale /= 1.2;
} else return;
// The default zoom factor is 1.2x for one scroll wheel click (delta==1).
// To support smooth scrolling where scroll wheel events come in increments
// smaller (or larger) than 1 we do:
// scale *= exp(ln(1.2) * delta);
// to ensure that the same total scroll delta always results in the same
// total zoom irrespective of in how many increments the zoom was applied.
// For example if we scroll a total delta of a+b in two events vs. one then
// scale * e^a * e^b == scale * e^(a+b)
// while
// scale * a * b != scale * (a+b)
// So this constant is ln(1.2) = 0.1823216 to make the default zoom 1.2x
scale *= exp(0.1823216 * delta);
double rightf = x/scale - offsetRight;
double upf = y/scale - offsetUp;

View File

@ -472,7 +472,7 @@ protected:
}
bool process_pointer_event(MouseEvent::Type type, double x, double y,
guint state, guint button = 0, int scroll_delta = 0) {
guint state, guint button = 0, double scroll_delta = 0) {
MouseEvent event = {};
event.type = type;
event.x = x;
@ -536,7 +536,7 @@ protected:
}
bool on_scroll_event(GdkEventScroll *gdk_event) override {
int delta;
double delta;
if(gdk_event->delta_y < 0 || gdk_event->direction == GDK_SCROLL_UP) {
delta = 1;
} else if(gdk_event->delta_y > 0 || gdk_event->direction == GDK_SCROLL_DOWN) {

View File

@ -554,7 +554,9 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
MouseEvent event = [self convertMouseEvent:nsEvent];
event.type = MouseEvent::Type::SCROLL_VERT;
event.scrollDelta = [nsEvent deltaY];
bool isPrecise = [nsEvent hasPreciseScrollingDeltas];
event.scrollDelta = [nsEvent scrollingDeltaY] / (isPrecise ? 50 : 5);
if(receiver->onMouseEvent) {
receiver->onMouseEvent(event);
@ -975,9 +977,6 @@ public:
if(GetScrollbarPosition() == pos)
return;
[nsScroller setDoubleValue:(pos / (ssView.scrollerMax - ssView.scrollerMin))];
if(onScrollbarAdjusted) {
onScrollbarAdjusted(pos);
}
}
void Invalidate() override {

View File

@ -925,7 +925,7 @@ public:
event.y = pt.y / pixelRatio;
event.type = MouseEvent::Type::SCROLL_VERT;
event.scrollDelta = GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? 1 : -1;
event.scrollDelta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
break;
case WM_MOUSELEAVE:

View File

@ -252,8 +252,18 @@ void TextWindow::Init() {
MouseLeave();
return true;
} else if(event.type == MouseEvent::Type::SCROLL_VERT) {
ScrollbarEvent(window->GetScrollbarPosition() -
LINE_HEIGHT / 2 * event.scrollDelta);
if (event.scrollDelta == 0) {
return true;
}
if (abs(event.scrollDelta) < 0.2) {
if (event.scrollDelta > 0) {
event.scrollDelta = 0.2;
} else {
event.scrollDelta = -0.2;
}
}
double offset = LINE_HEIGHT / 2 * event.scrollDelta;
ScrollbarEvent(window->GetScrollbarPosition() - offset);
}
return false;
};
@ -1148,7 +1158,6 @@ void TextWindow::ScrollbarEvent(double newPos) {
int bottom = top[rows-1] + 2;
newPos = min((int)newPos, bottom - halfRows);
newPos = max((int)newPos, 0);
if(newPos != scrollPos) {
scrollPos = (int)newPos;
window->SetScrollbarPosition(scrollPos);

View File

@ -825,7 +825,7 @@ public:
void MouseLeftDoubleClick(double x, double y);
void MouseMiddleOrRightDown(double x, double y);
void MouseRightUp(double x, double y);
void MouseScroll(double x, double y, int delta);
void MouseScroll(double x, double y, double delta);
void MouseLeave();
bool KeyboardEvent(Platform::KeyboardEvent event);
void EditControlDone(const std::string &s);