Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ff3cdf8
Add scroll_to_bottom() method to TerminalBackend
OlegKrakenTeam2 Feb 5, 2026
edf4f02
Add clear_history() method to TerminalBackend
OlegKrakenTeam2 Feb 5, 2026
86e4379
Fix scroll handling in alternate screen mode with MOUSE_MODE
OlegKrakenTeam2 Feb 5, 2026
5e0674d
Cleanup unused code
OrelSokolov Feb 5, 2026
d31aa9e
Add shell argument support to BackendSettings and use --login for bas…
OrelSokolov Feb 6, 2026
954385c
Add env support to BackendSettings with default TERM and COLORTERM
OrelSokolov Feb 6, 2026
825a69c
Updates for UP, DOWN
OrelSokolov Feb 8, 2026
a2468e5
Autoscrolling while input
OrelSokolov Feb 8, 2026
241c765
Add ScrollPageUp and ScrollPageDown support
OrelSokolov Feb 8, 2026
ae799dc
Add Ctrl+Shift+PageUp/Down bindings for terminal scrolling
OrelSokolov Feb 8, 2026
91eb799
Fix: kill child process when TerminalBackend is dropped
OrelSokolov Feb 9, 2026
5f6065f
Fix Ctrl+X handling in terminal
OrelSokolov Feb 10, 2026
771ea50
Fix bracketed paste support in terminal
OrelSokolov Feb 10, 2026
00613fb
Fix: add newline characters when copying multi-line terminal text
OrelSokolov Feb 11, 2026
eb21702
docs: update README with fork differences
OrelSokolov Feb 11, 2026
cc0c251
feat: add search functionality with CTRL+F toggle
OrelSokolov Feb 12, 2026
2224c63
fix: focus handling when search panel is active
OrelSokolov Feb 12, 2026
3f83869
fix: auto-focus search input when panel opens
OrelSokolov Feb 12, 2026
fe8eb9f
fix: proper focus handling using ctx.memory_mut like settings window
OrelSokolov Feb 12, 2026
56ce716
refactor: remove search UI from egui_term, keep only search API
OrelSokolov Feb 12, 2026
ae6e348
fix: kill entire process group on tab close to prevent orphaned children
OrelSokolov May 1, 2026
01c3aea
Fixes for windows
OrelSokolov May 30, 2026
48fbc5d
Fixes
OlegKrakenTeam2 May 30, 2026
d7fa9d1
Update dependencies: egui 0.34, eframe 0.34, wgpu 29, egui_dock 0.19.…
OrelSokolov Jun 6, 2026
77af64e
fix: avoid UI thread blocking on terminal FairMutex during sync()
OrelSokolov Jun 24, 2026
34de807
feat: support transparent terminal background (#RRGGBBAA)
OrelSokolov Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
852 changes: 500 additions & 352 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ members = ["examples/*"]

# dependencies that are shared throughout the workspace (mostly for examples)
[workspace.dependencies]
egui = "0.33"
eframe = { version = "0.33", default-features = false, features = [
egui = "0.34"
eframe = { version = "0.34", default-features = false, features = [
"accesskit", # Make egui compatible with screen readers. NOTE: adds a lot of dependencies.
"default_fonts", # Embed the default egui fonts.
"wgpu", # Use the glow rendering backend. Alternative: "wgpu".
"persistence", # Enable restoring app state when restarting the app.
] }
env_logger = "0.11.6"
log = "0.4"
wgpu = "27" # enables the wgpu default features so we get the default backends
wgpu = "29" # enables the wgpu default features so we get the default backends

[package]
name = "egui_term"
Expand All @@ -29,3 +29,7 @@ egui = { workspace = true }
alacritty_terminal = "0.25.1"
anyhow = "1.0.100"
open = "5.3.2"
libc = "0.2"

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading"] }
79 changes: 18 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,24 @@
<!-- markdownlint-disable MD041 MD033 MD045 -->
<div align="center">
# egui_term fork gives you:

# egui_term
## Bug Fixes

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like AI Slop that was not double checked by human

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Harzu
I am using this fixes every hour for about a week. Yes, I am not rust developer, I use LLM to create Rust Code.

But saying this is AI slop... Hm... Okay, but it works for me very well.

Never mind then.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your AI Agent is override README.md file, so I made a conclusion that you don't recheck this, so I made the second conclusion that this is AI Slop

@OrelSokolov OrelSokolov Feb 11, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Harzu , oh, this is MY WISH to override readme.md file. This is not for PR, this is just highlight of what I've found and fixed and what my fork does. This is readme for my fork.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Harzu I am not asking to merge this code, I am asking to view and may be you can find some good things and fixes for the main repository.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/OrelSokolov/yaaa I use your repo here, thank you!


[![GitHub License][license-badge]][license-link]
[![crates.io][crates.io-badge]][crates.io-link]
[![docs.rs][docs.rs-badge]][docs.rs-link]
[![Rust CI][ci-badge]][ci-link]
- **Copying multi-line text** — added newline characters when copying terminal text
- **Bracketed paste** — fixed proper bracketed paste support
- **Ctrl+X** — fixed handling (was intercepted by egui)
- **Kill child process** — proper termination when TerminalBackend is dropped
- **Alternate screen scroll** — fixed scroll handling in MOUSE_MODE

Terminal emulator widget powered by EGUI framework and alacritty terminal backend.
## New Features

<a href="./examples/full_screen">
<img src="examples/full_screen/assets/screenshot.png" width="275px">
</a>
<a href="./examples/tabs">
<img src="examples/tabs/assets/screenshot.png" width="273px">
</a>
- **Ctrl+Shift+PageUp/Down** — bindings for terminal scrolling
- **ScrollPageUp/ScrollPageDown** — page scrolling support
- **Autoscrolling** — automatic scrolling while input
- **UP/DOWN** — navigation key improvements
- **clear_history()** — method to clear terminal history
- **scroll_to_bottom()** — method to scroll to bottom
- **Shell arguments** — support for shell arguments (--login for bash)
- **ENV support** — TERM and COLORTERM in BackendSettings

</div>
---

## Features

The widget is currently under development and does not provide full terminal features make sure that widget is covered everything you want.

- PTY content rendering
- Multiple instance support
- Basic keyboard input
- Adding custom keyboard or mouse bindings
- Resizing
- Scrolling
- Focusing
- Selecting
- Changing Font/Color scheme
- Hyperlinks processing (hover/open)

This widget was tested on MacOS, Linux, and Windows.

## Examples

You can also look at [examples](./examples) directory for more information about widget using.

- [full_screen](./examples/full_screen/) - The basic example of terminal emulator.
- [tabs](./examples/tabs/) - The example with tab widget that show how multiple instance feature work.
- [custom_bindings](./examples/custom_bindings/) - The example that show how you can add custom keyboard or mouse bindings to your terminal emulator app.
- [themes](./examples/themes/) - The example that show how you can change terminal color scheme.
- [fonts](./examples/fonts/) - The examples that show how you can change font type or font size in your terminal emulator app.

## Dependencies

[![dependency status][deps.rs-badge]][deps.rs-link]

- [alacritty_terminal](https://github.com/alacritty/alacritty) (Apache-2.0)
- [anyhow](https://github.com/dtolnay/anyhow) (MIT OR Apache-2.0)
- [egui](https://github.com/emilk/egui) (MIT OR Apache-2.0)
- [open](https://github.com/Byron/open-rs) (MIT)

[license-badge]: https://img.shields.io/github/license/Harzu/egui_term
[license-link]: https://github.com/Harzu/egui_term/blob/main/LICENSE
[crates.io-badge]: https://img.shields.io/crates/v/egui_term
[crates.io-link]: https://crates.io/crates/egui_term
[docs.rs-badge]: https://img.shields.io/docsrs/egui_term
[docs.rs-link]: https://docs.rs/egui_term
[ci-badge]: https://github.com/Harzu/egui_term/actions/workflows/rust.yml/badge.svg
[ci-link]: https://github.com/Harzu/egui_term/actions/workflows/rust.yml
[deps.rs-badge]: https://img.shields.io/deps-rs/egui_term/latest?style=for-the-badge&label=dependency%20status
[deps.rs-link]: https://deps.rs/crate/egui_term
Forked from [Harzu/egui_term](https://github.com/Harzu/egui_term)
3 changes: 2 additions & 1 deletion examples/custom_bindings/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ impl App {
}

impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx();
if let Ok((_, PtyEvent::Exit)) = self.pty_proxy_receiver.try_recv() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
return;
Expand Down
3 changes: 2 additions & 1 deletion examples/fonts/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ impl App {
}

impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx();
if let Ok((_, PtyEvent::Exit)) = self.pty_proxy_receiver.try_recv() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
return;
Expand Down
3 changes: 2 additions & 1 deletion examples/full_screen/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ impl App {
}

impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx();
if let Ok((_, PtyEvent::Exit)) = self.pty_proxy_receiver.try_recv() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
return;
Expand Down
2 changes: 1 addition & 1 deletion examples/split_view/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"

[dependencies]
egui = { workspace = true }
egui_dock = "0.18.0"
egui_dock = "0.19.1"
eframe = { workspace = true }
log = { workspace = true }
egui_term = { path = "../../" }
Expand Down
3 changes: 2 additions & 1 deletion examples/split_view/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ impl App {
}

impl eframe::App for App {
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx();
DockArea::new(&mut self.dock_state)
.show_add_buttons(false)
.style(Style::from_egui(ctx.style().as_ref()))
Expand Down
1 change: 1 addition & 0 deletions examples/tabs/input_link
12 changes: 10 additions & 2 deletions examples/tabs/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ impl App {
}

impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx();
if ctx.input(|i| i.viewport().close_requested()) {
self.tab_manager.clear();
}
Expand Down Expand Up @@ -161,16 +162,23 @@ impl Tab {
) -> Self {
#[cfg(unix)]
let system_shell =
std::env::var("SHELL").expect("SHELL variable is not defined");
std::env::var("SHELL").unwrap_or_else(|_| "bash".to_string());
#[cfg(windows)]
let system_shell = "cmd.exe".to_string();

let shell_args = if system_shell.contains("bash") {
vec!["--login".to_string()]
} else {
vec![]
};

let backend = TerminalBackend::new(
id,
ctx,
command_sender,
egui_term::BackendSettings {
shell: system_shell,
args: shell_args,
..Default::default()
},
)
Expand Down
3 changes: 2 additions & 1 deletion examples/themes/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ impl App {
}

impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx();
if let Ok((_, PtyEvent::Exit)) = self.pty_proxy_receiver.try_recv() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
return;
Expand Down
81 changes: 81 additions & 0 deletions notes/ALTERNATE_SCROLL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# ALTERNATE_SCROLL Fix

## Problem

Mouse wheel scrolling was not working correctly in applications using ncurses with alternate screen mode (e.g., opencode, tmux, less, vim). Instead of scrolling the content within the application, the terminal was sending arrow key sequences (ESC O A / ESC O B).

## Root Cause

The issue was in the scroll handling logic in `src/view.rs` and `src/backend/mod.rs`:

1. **Incorrect priority check**: The condition `terminal.mode().contains(TermMode::ALTERNATE_SCROLL | TermMode::ALT_SCREEN)` would return `true` even when `MOUSE_MODE` was active, because `contains()` checks if ANY of the flags are present.

2. **Missing terminal mode priority**: When `MOUSE_MODE` (specifically `SGR_MOUSE`) is active in ncurses applications, the application expects mouse wheel events via SGR protocol, not arrow key sequences.

3. **Focus/pointer check issue**: All input events were blocked if either focus was lost OR pointer was outside widget, which prevented scroll from working even when the mouse was over the widget.

## Solution

### 1. Corrected terminal mode priority

Updated scroll handling in `src/view.rs` to follow alacrity's priority order:

```rust
// Priority 1: MOUSE_MODE (SGR_MOUSE active) → Send mouse wheel report
if terminal_mode.intersects(TermMode::MOUSE_MODE) {
// Send SGR mouse wheel report
}
// Priority 2: ALT_SCREEN | ALTERNATE_SCROLL → Send arrow keys
else if terminal_mode.contains(TermMode::ALT_SCREEN | TermMode::ALTERNATE_SCROLL) {
// Send ESC O A / ESC O B
}
// Priority 3: Default → Scroll viewport
else {
// Scroll terminal viewport
}
```

Key changes:
- Use `intersects()` for `MOUSE_MODE` check (it's a combination of multiple flags)
- Ensure MOUSE_MODE is checked BEFORE ALTERNATE_SCROLL
- Use `contains()` for ALT_SCREEN | ALTERNATE_SCROLL combination

### 2. Separated keyboard and mouse event handling

Modified `process_input()` in `src/view.rs` to have different focus requirements:

- **Keyboard events** (Text, Key, Copy, Paste): Require `layout.has_focus()`
- **Mouse events** (MouseWheel, PointerButton, PointerMoved): Require `layout.contains_pointer()`

This allows mouse wheel to work even when keyboard focus is on different widgets.

### 3. Inverted scroll direction

Adjusted scroll direction to match standard behavior:

- **Mouse wheel up** → Scroll content up (send ScrollUp / ESC O A)
- **Mouse wheel down** → Scroll content down (send ScrollDown / ESC O B)

## Files Changed

- `src/view.rs`:
- Modified `process_input()` to separate keyboard/mouse event handling
- Rewrote `process_mouse_wheel()` with correct terminal mode priority
- Removed rigid focus check at the start

- `src/backend/mod.rs`:
- Simplified `scroll()` function to only handle viewport scrolling

## Testing

Tested with opencode (ncurses-based application) in alternate screen mode:
- ✅ Mouse wheel now correctly scrolls application content
- ✅ Mouse wheel events are sent via SGR protocol when MOUSE_MODE is active
- ✅ Scroll direction matches standard behavior
- ✅ Works without requiring explicit focus

## References

- Alacrity scroll handling: `alacritty/src/input/mod.rs` - `scroll_terminal()` function
- Terminal mode definitions: `alacritty_terminal/src/term/mod.rs` - `TermMode` enum
- DEC Private Mode 1007 (ALTERNATE_SCROLL): Controls arrow key substitution for scroll events
Loading