diff --git a/ImGuiInputHandler.cc b/ImGuiInputHandler.cc index 8abd7f3..7c2d4b7 100644 --- a/ImGuiInputHandler.cc +++ b/ImGuiInputHandler.cc @@ -294,25 +294,34 @@ ImGuiInputHandler::ProcessSDLEvent(const SDL_Event &e) bool produced = false; switch (e.type) { case SDL_MOUSEWHEEL: { - // Let ImGui handle mouse wheel when it wants to capture the mouse - // (e.g., when hovering the editor child window with scrollbars). - // This enables native vertical and horizontal scrolling behavior in GUI. - if (ImGui::GetIO().WantCaptureMouse) - return false; - // Otherwise, fallback to mapping vertical wheel to editor scroll commands. - int dy = e.wheel.y; + // High-resolution trackpads can deliver fractional wheel deltas. Accumulate + // precise values and emit one scroll step per whole unit. + float dy = 0.0f; +#if SDL_VERSION_ATLEAST(2,0,18) + dy = e.wheel.preciseY; +#else + dy = static_cast(e.wheel.y); +#endif #ifdef SDL_MOUSEWHEEL_FLIPPED if (e.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) dy = -dy; #endif - if (dy != 0) { - int repeat = dy > 0 ? dy : -dy; - CommandId id = dy > 0 ? CommandId::ScrollUp : CommandId::ScrollDown; - std::lock_guard lk(mu_); - for (int i = 0; i < repeat; ++i) { - q_.push(MappedInput{true, id, std::string(), 0}); + if (dy != 0.0f) { + wheel_accum_y_ += dy; + float abs_accum = wheel_accum_y_ >= 0.0f ? wheel_accum_y_ : -wheel_accum_y_; + int steps = static_cast(abs_accum); + if (steps > 0) { + CommandId id = (wheel_accum_y_ > 0.0f) ? CommandId::ScrollUp : CommandId::ScrollDown; + std::lock_guard lk(mu_); + for (int i = 0; i < steps; ++i) { + q_.push(MappedInput{true, id, std::string(), 0}); + } + // remove the whole steps, keep fractional remainder + wheel_accum_y_ += (wheel_accum_y_ > 0.0f) + ? -static_cast(steps) + : static_cast(steps); + return true; // consumed } - return true; // consumed } return false; } diff --git a/ImGuiInputHandler.h b/ImGuiInputHandler.h index 7237bc1..02881ab 100644 --- a/ImGuiInputHandler.h +++ b/ImGuiInputHandler.h @@ -41,4 +41,9 @@ private: bool suppress_text_input_once_ = false; Editor *ed_ = nullptr; // attached editor for editor-owned uarg handling + + // Accumulators for high-resolution (trackpad) scrolling. We emit one scroll + // command per whole step and keep the fractional remainder. + float wheel_accum_y_ = 0.0f; + float wheel_accum_x_ = 0.0f; // reserved for future horizontal scrolling }; \ No newline at end of file diff --git a/TerminalFrontend.cc b/TerminalFrontend.cc index e8218ad..7ab0fad 100644 --- a/TerminalFrontend.cc +++ b/TerminalFrontend.cc @@ -42,13 +42,15 @@ TerminalFrontend::Init(Editor &ed) meta(stdscr, TRUE); // Make ESC key sequences resolve quickly so ESC+ works as meta #ifdef set_escdelay - set_escdelay(50); + set_escdelay(TerminalFrontend::kEscDelayMs); #endif - nodelay(stdscr, TRUE); + // Make getch() block briefly instead of busy-looping; reduces CPU when idle + // Equivalent to nodelay(FALSE) with a small timeout. + timeout(16); // ~16ms (about 60Hz) curs_set(1); // Enable mouse support if available mouseinterval(0); - mousemask(ALL_MOUSE_EVENTS, nullptr); + mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, nullptr); int r = 0, c = 0; getmaxyx(stdscr, r, c); @@ -94,9 +96,6 @@ TerminalFrontend::Step(Editor &ed, bool &running) if (mi.hasCommand) { Execute(ed, mi.id, mi.arg, mi.count); } - } else { - // Avoid busy loop - usleep(1000); } if (ed.QuitRequested()) { diff --git a/TerminalFrontend.h b/TerminalFrontend.h index b1af4a7..1afc27d 100644 --- a/TerminalFrontend.h +++ b/TerminalFrontend.h @@ -16,6 +16,11 @@ public: ~TerminalFrontend() override = default; + // Configurable ESC key delay (ms) for ncurses' set_escdelay(). + // Controls how long ncurses waits to distinguish ESC vs. meta sequences. + // Adjust if your terminal needs a different threshold. + static constexpr int kEscDelayMs = 50; + bool Init(Editor &ed) override; void Step(Editor &ed, bool &running) override;