mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
termio: stop the termios poller when not focused
This commit is contained in:
@ -1826,17 +1826,12 @@ pub fn focusCallback(self: *Surface, focused: bool) !void {
|
|||||||
// Schedule render which also drains our mailbox
|
// Schedule render which also drains our mailbox
|
||||||
try self.queueRender();
|
try self.queueRender();
|
||||||
|
|
||||||
// Update the focus state and notify the terminal about the focus event if
|
// Update the focus state and notify the terminal
|
||||||
// it is requesting it
|
|
||||||
{
|
{
|
||||||
self.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
self.io.terminal.flags.focused = focused;
|
self.io.terminal.flags.focused = focused;
|
||||||
const focus_event = self.io.terminal.modes.get(.focus_event);
|
|
||||||
self.renderer_state.mutex.unlock();
|
self.renderer_state.mutex.unlock();
|
||||||
|
self.io.queueMessage(.{ .focused = focused }, .unlocked);
|
||||||
if (focus_event) {
|
|
||||||
self.io.queueMessage(.{ .focused = focused }, .unlocked);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +196,32 @@ pub fn threadExit(self: *Exec, td: *termio.Termio.ThreadData) void {
|
|||||||
exec.read_thread.join();
|
exec.read_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn focusGained(
|
||||||
|
self: *Exec,
|
||||||
|
td: *termio.Termio.ThreadData,
|
||||||
|
focused: bool,
|
||||||
|
) !void {
|
||||||
|
_ = self;
|
||||||
|
|
||||||
|
assert(td.backend == .exec);
|
||||||
|
const execdata = &td.backend.exec;
|
||||||
|
|
||||||
|
if (!focused) {
|
||||||
|
// Flag the timer to end on the next iteration. This is
|
||||||
|
// a lot cheaper than doing full timer cancellation.
|
||||||
|
execdata.termios_timer_running = false;
|
||||||
|
} else {
|
||||||
|
// If we're focused, we want to start our termios timer. We
|
||||||
|
// only do this if it isn't already running. We use the termios
|
||||||
|
// callback because that'll trigger an immediate state check AND
|
||||||
|
// start the timer.
|
||||||
|
if (execdata.termios_timer_c.state() != .active) {
|
||||||
|
execdata.termios_timer_running = true;
|
||||||
|
_ = termiosTimer(td, undefined, undefined, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resize(
|
pub fn resize(
|
||||||
self: *Exec,
|
self: *Exec,
|
||||||
grid_size: renderer.GridSize,
|
grid_size: renderer.GridSize,
|
||||||
@ -391,6 +417,8 @@ fn termiosTimer(
|
|||||||
_: *xev.Completion,
|
_: *xev.Completion,
|
||||||
r: xev.Timer.RunError!void,
|
r: xev.Timer.RunError!void,
|
||||||
) xev.CallbackAction {
|
) xev.CallbackAction {
|
||||||
|
// log.debug("termios timer fired", .{});
|
||||||
|
|
||||||
// This should never happen because we guard starting our
|
// This should never happen because we guard starting our
|
||||||
// timer on windows but we want this assertion to fire if
|
// timer on windows but we want this assertion to fire if
|
||||||
// we ever do start the timer on windows.
|
// we ever do start the timer on windows.
|
||||||
@ -448,14 +476,16 @@ fn termiosTimer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Repeat the timer
|
// Repeat the timer
|
||||||
exec.termios_timer.run(
|
if (exec.termios_timer_running) {
|
||||||
td.loop,
|
exec.termios_timer.run(
|
||||||
&exec.termios_timer_c,
|
td.loop,
|
||||||
TERMIOS_POLL_MS,
|
&exec.termios_timer_c,
|
||||||
termio.Termio.ThreadData,
|
TERMIOS_POLL_MS,
|
||||||
td,
|
termio.Termio.ThreadData,
|
||||||
termiosTimer,
|
td,
|
||||||
);
|
termiosTimer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return .disarm;
|
return .disarm;
|
||||||
}
|
}
|
||||||
@ -604,6 +634,7 @@ pub const ThreadData = struct {
|
|||||||
/// The timer to detect termios state changes.
|
/// The timer to detect termios state changes.
|
||||||
termios_timer: xev.Timer,
|
termios_timer: xev.Timer,
|
||||||
termios_timer_c: xev.Completion = .{},
|
termios_timer_c: xev.Completion = .{},
|
||||||
|
termios_timer_running: bool = true,
|
||||||
|
|
||||||
/// The last known termios mode. Used for change detection
|
/// The last known termios mode. Used for change detection
|
||||||
/// to prevent unnecessary locking of expensive mutexes.
|
/// to prevent unnecessary locking of expensive mutexes.
|
||||||
|
@ -523,8 +523,18 @@ pub fn childExitedAbnormally(self: *Termio, exit_code: u32, runtime_ms: u64) !vo
|
|||||||
|
|
||||||
/// Called when focus is gained or lost (when focus events are enabled)
|
/// Called when focus is gained or lost (when focus events are enabled)
|
||||||
pub fn focusGained(self: *Termio, td: *ThreadData, focused: bool) !void {
|
pub fn focusGained(self: *Termio, td: *ThreadData, focused: bool) !void {
|
||||||
const seq = if (focused) "\x1b[I" else "\x1b[O";
|
self.renderer_state.mutex.lock();
|
||||||
try self.queueWrite(td, seq, false);
|
const focus_event = self.renderer_state.terminal.modes.get(.focus_event);
|
||||||
|
self.renderer_state.mutex.unlock();
|
||||||
|
|
||||||
|
// If we have focus events enabled, we send the focus event.
|
||||||
|
if (focus_event) {
|
||||||
|
const seq = if (focused) "\x1b[I" else "\x1b[O";
|
||||||
|
try self.queueWrite(td, seq, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We always notify our backend of focus changes.
|
||||||
|
try self.backend.focusGained(td, focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process output from the pty. This is the manual API that users can
|
/// Process output from the pty. This is the manual API that users can
|
||||||
|
@ -62,6 +62,16 @@ pub const Backend = union(Kind) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn focusGained(
|
||||||
|
self: *Backend,
|
||||||
|
td: *termio.Termio.ThreadData,
|
||||||
|
focused: bool,
|
||||||
|
) !void {
|
||||||
|
switch (self.*) {
|
||||||
|
.exec => |*exec| try exec.focusGained(td, focused),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resize(
|
pub fn resize(
|
||||||
self: *Backend,
|
self: *Backend,
|
||||||
grid_size: renderer.GridSize,
|
grid_size: renderer.GridSize,
|
||||||
|
Reference in New Issue
Block a user