Add ScrollUp and ScrollDown commands for viewport scrolling, refine mouse wheel handling in GUI and terminal, and bump version to 1.2.2.
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
Release / Build Linux amd64 (push) Has been cancelled
Release / Build Linux arm64 (push) Has been cancelled
Release / Build macOS arm64 (.app) (push) Has been cancelled
Release / Create GitHub Release (push) Has been cancelled
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
Release / Build Linux amd64 (push) Has been cancelled
Release / Build Linux arm64 (push) Has been cancelled
Release / Build macOS arm64 (.app) (push) Has been cancelled
Release / Create GitHub Release (push) Has been cancelled
This commit is contained in:
@@ -4,7 +4,7 @@ project(kte)
|
|||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(KTE_VERSION "1.2.1")
|
set(KTE_VERSION "1.2.2")
|
||||||
|
|
||||||
# Default to terminal-only build to avoid SDL/OpenGL dependency by default.
|
# Default to terminal-only build to avoid SDL/OpenGL dependency by default.
|
||||||
# Enable with -DBUILD_GUI=ON when SDL2/OpenGL/Freetype are available.
|
# Enable with -DBUILD_GUI=ON when SDL2/OpenGL/Freetype are available.
|
||||||
|
|||||||
70
Command.cc
70
Command.cc
@@ -3067,6 +3067,74 @@ cmd_page_down(CommandContext &ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmd_scroll_up(CommandContext &ctx)
|
||||||
|
{
|
||||||
|
Buffer *buf = ctx.editor.CurrentBuffer();
|
||||||
|
if (!buf)
|
||||||
|
return false;
|
||||||
|
ensure_at_least_one_line(*buf);
|
||||||
|
const auto &rows = buf->Rows();
|
||||||
|
std::size_t content_rows = std::max<std::size_t>(1, ctx.editor.ContentRows());
|
||||||
|
std::size_t rowoffs = buf->Rowoffs();
|
||||||
|
|
||||||
|
// Scroll up by 3 lines (or count if specified), without moving cursor
|
||||||
|
int scroll_amount = ctx.count > 0 ? ctx.count : 3;
|
||||||
|
if (rowoffs >= static_cast<std::size_t>(scroll_amount))
|
||||||
|
rowoffs -= static_cast<std::size_t>(scroll_amount);
|
||||||
|
else
|
||||||
|
rowoffs = 0;
|
||||||
|
|
||||||
|
buf->SetOffsets(rowoffs, buf->Coloffs());
|
||||||
|
|
||||||
|
// If cursor is now below the visible area, move it to the last visible line
|
||||||
|
std::size_t cury = buf->Cury();
|
||||||
|
if (cury >= rowoffs + content_rows) {
|
||||||
|
std::size_t new_y = rowoffs + content_rows - 1;
|
||||||
|
if (new_y >= rows.size() && !rows.empty())
|
||||||
|
new_y = rows.size() - 1;
|
||||||
|
buf->SetCursor(buf->Curx(), new_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmd_scroll_down(CommandContext &ctx)
|
||||||
|
{
|
||||||
|
Buffer *buf = ctx.editor.CurrentBuffer();
|
||||||
|
if (!buf)
|
||||||
|
return false;
|
||||||
|
ensure_at_least_one_line(*buf);
|
||||||
|
const auto &rows = buf->Rows();
|
||||||
|
std::size_t content_rows = std::max<std::size_t>(1, ctx.editor.ContentRows());
|
||||||
|
std::size_t rowoffs = buf->Rowoffs();
|
||||||
|
|
||||||
|
// Scroll down by 3 lines (or count if specified), without moving cursor
|
||||||
|
int scroll_amount = ctx.count > 0 ? ctx.count : 3;
|
||||||
|
|
||||||
|
// Compute maximum top offset
|
||||||
|
std::size_t max_top = 0;
|
||||||
|
if (!rows.empty() && rows.size() > content_rows)
|
||||||
|
max_top = rows.size() - content_rows;
|
||||||
|
|
||||||
|
rowoffs += static_cast<std::size_t>(scroll_amount);
|
||||||
|
if (rowoffs > max_top)
|
||||||
|
rowoffs = max_top;
|
||||||
|
|
||||||
|
buf->SetOffsets(rowoffs, buf->Coloffs());
|
||||||
|
|
||||||
|
// If cursor is now above the visible area, move it to the first visible line
|
||||||
|
std::size_t cury = buf->Cury();
|
||||||
|
if (cury < rowoffs) {
|
||||||
|
buf->SetCursor(buf->Curx(), rowoffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
is_word_char(unsigned char c)
|
is_word_char(unsigned char c)
|
||||||
{
|
{
|
||||||
@@ -3675,6 +3743,8 @@ InstallDefaultCommands()
|
|||||||
CommandRegistry::Register({CommandId::MoveEnd, "end", "Move to end of line", cmd_move_end});
|
CommandRegistry::Register({CommandId::MoveEnd, "end", "Move to end of line", cmd_move_end});
|
||||||
CommandRegistry::Register({CommandId::PageUp, "page-up", "Page up", cmd_page_up});
|
CommandRegistry::Register({CommandId::PageUp, "page-up", "Page up", cmd_page_up});
|
||||||
CommandRegistry::Register({CommandId::PageDown, "page-down", "Page down", cmd_page_down});
|
CommandRegistry::Register({CommandId::PageDown, "page-down", "Page down", cmd_page_down});
|
||||||
|
CommandRegistry::Register({CommandId::ScrollUp, "scroll-up", "Scroll viewport up", cmd_scroll_up});
|
||||||
|
CommandRegistry::Register({CommandId::ScrollDown, "scroll-down", "Scroll viewport down", cmd_scroll_down});
|
||||||
CommandRegistry::Register({CommandId::WordPrev, "word-prev", "Move to previous word", cmd_word_prev});
|
CommandRegistry::Register({CommandId::WordPrev, "word-prev", "Move to previous word", cmd_word_prev});
|
||||||
CommandRegistry::Register({CommandId::WordNext, "word-next", "Move to next word", cmd_word_next});
|
CommandRegistry::Register({CommandId::WordNext, "word-next", "Move to next word", cmd_word_next});
|
||||||
CommandRegistry::Register({
|
CommandRegistry::Register({
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ enum class CommandId {
|
|||||||
MoveEnd,
|
MoveEnd,
|
||||||
PageUp,
|
PageUp,
|
||||||
PageDown,
|
PageDown,
|
||||||
|
ScrollUp, // scroll viewport up (towards beginning) without moving cursor
|
||||||
|
ScrollDown, // scroll viewport down (towards end) without moving cursor
|
||||||
WordPrev,
|
WordPrev,
|
||||||
WordNext,
|
WordNext,
|
||||||
DeleteWordPrev, // delete previous word (ESC BACKSPACE)
|
DeleteWordPrev, // delete previous word (ESC BACKSPACE)
|
||||||
|
|||||||
@@ -285,15 +285,11 @@ GUIInputHandler::ProcessSDLEvent(const SDL_Event &e)
|
|||||||
bool produced = false;
|
bool produced = false;
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case SDL_MOUSEWHEEL: {
|
case SDL_MOUSEWHEEL: {
|
||||||
// If ImGui wants to capture the mouse (e.g., hovering the File Picker list),
|
// Map vertical wheel to viewport scrolling (ScrollUp/ScrollDown)
|
||||||
// don't translate wheel events into editor scrolling.
|
// Note: We don't check WantCaptureMouse here because ImGui sets it to true
|
||||||
// This prevents background buffer scroll while using GUI widgets.
|
// whenever the mouse is over any ImGui window (including our editor content area).
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
// The NoScrollWithMouse flag on the child window prevents ImGui from handling
|
||||||
if (io.WantCaptureMouse) {
|
// scroll internally, so we can safely process wheel events ourselves.
|
||||||
return true; // consumed by GUI
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map vertical wheel to line-wise cursor movement (MoveUp/MoveDown)
|
|
||||||
int dy = e.wheel.y;
|
int dy = e.wheel.y;
|
||||||
#ifdef SDL_MOUSEWHEEL_FLIPPED
|
#ifdef SDL_MOUSEWHEEL_FLIPPED
|
||||||
if (e.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
|
if (e.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
|
||||||
@@ -301,7 +297,7 @@ GUIInputHandler::ProcessSDLEvent(const SDL_Event &e)
|
|||||||
#endif
|
#endif
|
||||||
if (dy != 0) {
|
if (dy != 0) {
|
||||||
int repeat = dy > 0 ? dy : -dy;
|
int repeat = dy > 0 ? dy : -dy;
|
||||||
CommandId id = dy > 0 ? CommandId::MoveUp : CommandId::MoveDown;
|
CommandId id = dy > 0 ? CommandId::ScrollUp : CommandId::ScrollDown;
|
||||||
std::lock_guard<std::mutex> lk(mu_);
|
std::lock_guard<std::mutex> lk(mu_);
|
||||||
for (int i = 0; i < repeat; ++i) {
|
for (int i = 0; i < repeat; ++i) {
|
||||||
q_.push(MappedInput{true, id, std::string(), 0});
|
q_.push(MappedInput{true, id, std::string(), 0});
|
||||||
@@ -564,7 +560,12 @@ GUIInputHandler::ProcessSDLEvent(const SDL_Event &e)
|
|||||||
|
|
||||||
if (produced && mi.hasCommand) {
|
if (produced && mi.hasCommand) {
|
||||||
// Attach universal-argument count if present, then clear the state
|
// Attach universal-argument count if present, then clear the state
|
||||||
if (uarg_active_ && mi.id != CommandId::UArgStatus) {
|
if (uarg_active_ &&mi
|
||||||
|
|
||||||
|
.
|
||||||
|
id != CommandId::UArgStatus
|
||||||
|
)
|
||||||
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (!uarg_had_digits_ && !uarg_negative_) {
|
if (!uarg_had_digits_ && !uarg_negative_) {
|
||||||
count = (uarg_value_ > 0) ? uarg_value_ : 4;
|
count = (uarg_value_ > 0) ? uarg_value_ : 4;
|
||||||
|
|||||||
@@ -35,16 +35,16 @@ map_key_to_command(const int ch,
|
|||||||
case KEY_MOUSE: {
|
case KEY_MOUSE: {
|
||||||
MEVENT ev{};
|
MEVENT ev{};
|
||||||
if (getmouse(&ev) == OK) {
|
if (getmouse(&ev) == OK) {
|
||||||
// Mouse wheel → map to MoveUp/MoveDown one line per wheel notch
|
// Mouse wheel → scroll viewport without moving cursor
|
||||||
#ifdef BUTTON4_PRESSED
|
#ifdef BUTTON4_PRESSED
|
||||||
if (ev.bstate & (BUTTON4_PRESSED | BUTTON4_RELEASED | BUTTON4_CLICKED)) {
|
if (ev.bstate & (BUTTON4_PRESSED | BUTTON4_RELEASED | BUTTON4_CLICKED)) {
|
||||||
out = {true, CommandId::MoveUp, "", 0};
|
out = {true, CommandId::ScrollUp, "", 0};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUTTON5_PRESSED
|
#ifdef BUTTON5_PRESSED
|
||||||
if (ev.bstate & (BUTTON5_PRESSED | BUTTON5_RELEASED | BUTTON5_CLICKED)) {
|
if (ev.bstate & (BUTTON5_PRESSED | BUTTON5_RELEASED | BUTTON5_CLICKED)) {
|
||||||
out = {true, CommandId::MoveDown, "", 0};
|
out = {true, CommandId::ScrollDown, "", 0};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user