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.
|
that are shortcuts to the respective configuration screens.
|
||||||
* New cmake build options using -DENABLE_OPENMP=yes and -DENABLE_LTO=yes
|
* New cmake build options using -DENABLE_OPENMP=yes and -DENABLE_LTO=yes
|
||||||
to enable support for multi-threading and link-time optimization.
|
to enable support for multi-threading and link-time optimization.
|
||||||
|
* "Shift+Scroll" for ten times finer zoom.
|
||||||
|
|
||||||
Bugs fixed:
|
Bugs fixed:
|
||||||
* Fixed broken --view options for command line thumbnail image creation.
|
* 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) {
|
bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) {
|
||||||
using Platform::MouseEvent;
|
using Platform::MouseEvent;
|
||||||
|
|
||||||
double width, height;
|
double width, height;
|
||||||
window->GetContentSize(&width, &height);
|
window->GetContentSize(&width, &height);
|
||||||
|
|
||||||
|
@ -918,7 +917,7 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MouseEvent::Type::SCROLL_VERT:
|
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;
|
break;
|
||||||
|
|
||||||
case MouseEvent::Type::LEAVE:
|
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 offsetRight = offset.Dot(projRight);
|
||||||
double offsetUp = offset.Dot(projUp);
|
double offsetUp = offset.Dot(projUp);
|
||||||
|
|
||||||
double righti = x/scale - offsetRight;
|
double righti = x/scale - offsetRight;
|
||||||
double upi = y/scale - offsetUp;
|
double upi = y/scale - offsetUp;
|
||||||
|
|
||||||
if(delta > 0) {
|
// The default zoom factor is 1.2x for one scroll wheel click (delta==1).
|
||||||
scale *= 1.2;
|
// To support smooth scrolling where scroll wheel events come in increments
|
||||||
} else if(delta < 0) {
|
// smaller (or larger) than 1 we do:
|
||||||
scale /= 1.2;
|
// scale *= exp(ln(1.2) * delta);
|
||||||
} else return;
|
// 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 rightf = x/scale - offsetRight;
|
||||||
double upf = y/scale - offsetUp;
|
double upf = y/scale - offsetUp;
|
||||||
|
|
|
@ -472,7 +472,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool process_pointer_event(MouseEvent::Type type, double x, double y,
|
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 = {};
|
MouseEvent event = {};
|
||||||
event.type = type;
|
event.type = type;
|
||||||
event.x = x;
|
event.x = x;
|
||||||
|
@ -536,7 +536,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool on_scroll_event(GdkEventScroll *gdk_event) override {
|
bool on_scroll_event(GdkEventScroll *gdk_event) override {
|
||||||
int delta;
|
double delta;
|
||||||
if(gdk_event->delta_y < 0 || gdk_event->direction == GDK_SCROLL_UP) {
|
if(gdk_event->delta_y < 0 || gdk_event->direction == GDK_SCROLL_UP) {
|
||||||
delta = 1;
|
delta = 1;
|
||||||
} else if(gdk_event->delta_y > 0 || gdk_event->direction == GDK_SCROLL_DOWN) {
|
} 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];
|
MouseEvent event = [self convertMouseEvent:nsEvent];
|
||||||
event.type = MouseEvent::Type::SCROLL_VERT;
|
event.type = MouseEvent::Type::SCROLL_VERT;
|
||||||
event.scrollDelta = [nsEvent deltaY];
|
|
||||||
|
bool isPrecise = [nsEvent hasPreciseScrollingDeltas];
|
||||||
|
event.scrollDelta = [nsEvent scrollingDeltaY] / (isPrecise ? 50 : 5);
|
||||||
|
|
||||||
if(receiver->onMouseEvent) {
|
if(receiver->onMouseEvent) {
|
||||||
receiver->onMouseEvent(event);
|
receiver->onMouseEvent(event);
|
||||||
|
@ -975,9 +977,6 @@ public:
|
||||||
if(GetScrollbarPosition() == pos)
|
if(GetScrollbarPosition() == pos)
|
||||||
return;
|
return;
|
||||||
[nsScroller setDoubleValue:(pos / (ssView.scrollerMax - ssView.scrollerMin))];
|
[nsScroller setDoubleValue:(pos / (ssView.scrollerMax - ssView.scrollerMin))];
|
||||||
if(onScrollbarAdjusted) {
|
|
||||||
onScrollbarAdjusted(pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Invalidate() override {
|
void Invalidate() override {
|
||||||
|
|
|
@ -925,7 +925,7 @@ public:
|
||||||
event.y = pt.y / pixelRatio;
|
event.y = pt.y / pixelRatio;
|
||||||
|
|
||||||
event.type = MouseEvent::Type::SCROLL_VERT;
|
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;
|
break;
|
||||||
|
|
||||||
case WM_MOUSELEAVE:
|
case WM_MOUSELEAVE:
|
||||||
|
|
|
@ -252,8 +252,18 @@ void TextWindow::Init() {
|
||||||
MouseLeave();
|
MouseLeave();
|
||||||
return true;
|
return true;
|
||||||
} else if(event.type == MouseEvent::Type::SCROLL_VERT) {
|
} else if(event.type == MouseEvent::Type::SCROLL_VERT) {
|
||||||
ScrollbarEvent(window->GetScrollbarPosition() -
|
if (event.scrollDelta == 0) {
|
||||||
LINE_HEIGHT / 2 * event.scrollDelta);
|
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;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -1148,7 +1158,6 @@ void TextWindow::ScrollbarEvent(double newPos) {
|
||||||
int bottom = top[rows-1] + 2;
|
int bottom = top[rows-1] + 2;
|
||||||
newPos = min((int)newPos, bottom - halfRows);
|
newPos = min((int)newPos, bottom - halfRows);
|
||||||
newPos = max((int)newPos, 0);
|
newPos = max((int)newPos, 0);
|
||||||
|
|
||||||
if(newPos != scrollPos) {
|
if(newPos != scrollPos) {
|
||||||
scrollPos = (int)newPos;
|
scrollPos = (int)newPos;
|
||||||
window->SetScrollbarPosition(scrollPos);
|
window->SetScrollbarPosition(scrollPos);
|
||||||
|
|
2
src/ui.h
2
src/ui.h
|
@ -825,7 +825,7 @@ public:
|
||||||
void MouseLeftDoubleClick(double x, double y);
|
void MouseLeftDoubleClick(double x, double y);
|
||||||
void MouseMiddleOrRightDown(double x, double y);
|
void MouseMiddleOrRightDown(double x, double y);
|
||||||
void MouseRightUp(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();
|
void MouseLeave();
|
||||||
bool KeyboardEvent(Platform::KeyboardEvent event);
|
bool KeyboardEvent(Platform::KeyboardEvent event);
|
||||||
void EditControlDone(const std::string &s);
|
void EditControlDone(const std::string &s);
|
||||||
|
|
Loading…
Reference in New Issue