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
parent
681a50db26
commit
2939abf5f8
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
2
src/ui.h
2
src/ui.h
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue