From 52bd8a8ce6be1e9242cba0414409c76fc78c5552 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 19 Apr 2026 16:42:42 +0530 Subject: [PATCH 01/23] Stub --- custom-prompt/Makefile | 16 +----------- custom-prompt/custom-prompt.cc | 8 +++++- custom-prompt/focus_utils.cc | 33 +++++++++++++++++++++++++ custom-prompt/focus_utils.hh | 20 +++++++++++++++ custom-prompt/get_active_wid.hh | 25 ------------------- custom-prompt/get_active_wid_linux.cc | 31 ----------------------- custom-prompt/get_active_wid_macos.m | 19 -------------- custom-prompt/get_active_wid_windows.cc | 8 ------ 8 files changed, 61 insertions(+), 99 deletions(-) create mode 100644 custom-prompt/focus_utils.cc create mode 100644 custom-prompt/focus_utils.hh delete mode 100644 custom-prompt/get_active_wid.hh delete mode 100644 custom-prompt/get_active_wid_linux.cc delete mode 100644 custom-prompt/get_active_wid_macos.m delete mode 100644 custom-prompt/get_active_wid_windows.cc diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index 38c5872d..8abebfb8 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -1,6 +1,4 @@ -CC = gcc CPPFLAGS = $(shell pkg-config --cflags libgit2) -CFLAGS = -fstrict-aliasing -std=c11 -Wall -Wextra -Wno-unused-parameter CXXFLAGS = -fstrict-aliasing -std=c++17 -Wall -Wextra -Wno-unused-parameter LDLIBS = -lstdc++ $(shell pkg-config --libs libgit2) @@ -9,25 +7,13 @@ MainBashObject = custom-bash-prompt.o MainBashExecutable = bin/$(MainBashObject:.o=) MainZshObject = custom-zsh-prompt.o MainZshExecutable = bin/$(MainZshObject:.o=) -OtherObjects = get_active_wid_linux.o get_active_wid_windows.o json_logger.o - -ifneq "$(OS)" "Windows_NT" - UNAME = $(shell uname) - ifeq "$(UNAME)" "Linux" - CPPFLAGS += $(shell pkg-config --cflags glib-2.0 libnotify x11) - LDLIBS += $(shell pkg-config --libs glib-2.0 libnotify x11) - else - LDLIBS += -framework Cocoa -framework CoreGraphics - OtherObjects += get_active_wid_macos.o - endif -endif +OtherObjects = focus_utils.o json_logger.o .PHONY: debug release debug: $(MainBashExecutable) $(MainZshExecutable) release: CPPFLAGS += -DNDEBUG -release: CFLAGS += -flto -O2 release: CXXFLAGS += -flto -O2 release: LDFLAGS += -flto -O2 release: debug diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index d4e6cac7..d259b383 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -14,7 +14,7 @@ #include #include -#include "get_active_wid.hh" +#include "focus_utils.hh" #include "json_logger.hh" namespace C @@ -663,11 +663,17 @@ void report_command_status( return; } +#ifdef _WIN32 long long unsigned curr_active_wid = get_active_wid(); LOG_DEBUG( logger, "Obtained focused window details", { { "previous", prev_active_wid }, { "current", curr_active_wid } } ); if (prev_active_wid != curr_active_wid) +#else + bool terminal_focused = terminal_has_focus(); + LOG_DEBUG(logger, "Obtained focus details", { { "terminal_focused", terminal_focused } }); + if (!terminal_focused) +#endif { notify_desktop(last_command, exit_code, interval); } diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc new file mode 100644 index 00000000..78aa978e --- /dev/null +++ b/custom-prompt/focus_utils.cc @@ -0,0 +1,33 @@ +#ifdef _WIN32 + +#include "focus_utils.hh" +#include + +long long unsigned get_active_wid(void) +{ + return static_cast(GetForegroundWindow()); +} + +bool terminal_has_focus(void) +{ + return false; +} + +#else //////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +long long unsigned get_active_wid(void) +{ + return 0; +} + +bool terminal_has_focus(void) +{ + return false; +} + +#endif diff --git a/custom-prompt/focus_utils.hh b/custom-prompt/focus_utils.hh new file mode 100644 index 00000000..b763c9c0 --- /dev/null +++ b/custom-prompt/focus_utils.hh @@ -0,0 +1,20 @@ +#ifndef FOCUS_UTILS_HH_ +#define FOCUS_UTILS_HH_ + +/* + * On Windows, obtain the ID of the active window. On Linux and macOS, do + * nothing. + * + * @return Active window ID or unspecified value (as described above). + */ +long long unsigned get_active_wid(void); + +/* + * On Linux and macOS, check whether the terminal has GUI focus. On Windows, do + * nothing. + * + * @return Focus state or unspecified value (as described above). + */ +bool terminal_has_focus(void); + +#endif diff --git a/custom-prompt/get_active_wid.hh b/custom-prompt/get_active_wid.hh deleted file mode 100644 index 3f1a6863..00000000 --- a/custom-prompt/get_active_wid.hh +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef GET_ACTIVE_WID_HH_ -#define GET_ACTIVE_WID_HH_ - -// clang-format off - -#ifdef __APPLE__ -extern "C" { -#endif - -/* - * On Linux, return the ID of the active window if X is running, else 0. - * - * On macOS, return the ID of the topmost window if one is found, else 0. - * - * On Windows, return the ID of the foreground window. - * - * @return Active window ID. - */ -long long unsigned get_active_wid(void); - -#ifdef __APPLE__ -} -#endif - -#endif diff --git a/custom-prompt/get_active_wid_linux.cc b/custom-prompt/get_active_wid_linux.cc deleted file mode 100644 index e46e9599..00000000 --- a/custom-prompt/get_active_wid_linux.cc +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef __linux__ -#include -#include - -long long unsigned get_active_wid(void) -{ - Display* display = XOpenDisplay(nullptr); - if (display == nullptr) - { - return 0; - } - - Window root_window = DefaultRootWindow(display); - Atom property = XInternAtom(display, "_NET_ACTIVE_WINDOW", False); - - Atom actual_type_return; - int actual_format_return; - long unsigned nitems_return; - long unsigned bytes_after_return; - char unsigned* prop_return; - XGetWindowProperty( - display, root_window, property, 0, 1, False, XA_WINDOW, &actual_type_return, &actual_format_return, - &nitems_return, &bytes_after_return, &prop_return - ); - - Window active_wid = *(Window*)prop_return; - // XFree(prop_return); - // XCloseDisplay(display); - return active_wid; -} -#endif diff --git a/custom-prompt/get_active_wid_macos.m b/custom-prompt/get_active_wid_macos.m deleted file mode 100644 index b236f99f..00000000 --- a/custom-prompt/get_active_wid_macos.m +++ /dev/null @@ -1,19 +0,0 @@ -#ifdef __APPLE__ -#include -#include - -long long unsigned get_active_wid(void) -{ - NSArray *windows = (NSArray *)CGWindowListCopyWindowInfo( - kCGWindowListExcludeDesktopElements | kCGWindowListOptionOnScreenOnly, kCGNullWindowID); - for (NSDictionary *window in windows) - { - int windowLayer = [[window objectForKey: (NSString *)kCGWindowLayer] intValue]; - if (windowLayer == 0) - { - return [[window objectForKey: (NSString *)kCGWindowNumber] intValue]; - } - } - return 0; -} -#endif diff --git a/custom-prompt/get_active_wid_windows.cc b/custom-prompt/get_active_wid_windows.cc deleted file mode 100644 index 4f7a1130..00000000 --- a/custom-prompt/get_active_wid_windows.cc +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef _WIN32 -#include - -long long unsigned get_active_wid(void) -{ - return (long long unsigned)GetForegroundWindow(); -} -#endif From 771053af8310e6b5e88a5c079298713f82aef035 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 19 Apr 2026 16:44:06 +0530 Subject: [PATCH 02/23] a --- custom-prompt/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index 8abebfb8..b3c8c45f 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -9,6 +9,12 @@ MainZshObject = custom-zsh-prompt.o MainZshExecutable = bin/$(MainZshObject:.o=) OtherObjects = focus_utils.o json_logger.o +UNAME = $(shell uname) +ifeq "$(UNAME)" "Linux" + CPPFLAGS += $(shell pkg-config --cflags libnotify) + LDLIBS += $(shell pkg-config --libs libnotify) +endif + .PHONY: debug release debug: $(MainBashExecutable) $(MainZshExecutable) From d0f0298532e88b80037fa8c9c35ca5a3875a43f6 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 19 Apr 2026 22:42:30 +0530 Subject: [PATCH 03/23] Add automatic terminal setting changing logic --- custom-prompt/focus_utils.cc | 53 ++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 78aa978e..b747b3c0 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -1,8 +1,9 @@ #ifdef _WIN32 -#include "focus_utils.hh" #include +#include "focus_utils.hh" + long long unsigned get_active_wid(void) { return static_cast(GetForegroundWindow()); @@ -15,18 +16,64 @@ bool terminal_has_focus(void) #else //////////////////////////////////////////////////////////////////////// -#include - +#include #include #include +#include "focus_utils.hh" + long long unsigned get_active_wid(void) { return 0; } +class NonBlockingStandardInputReader +{ +private: + bool error_occurred; + termios prev_termios, curr_termios; + +public: + NonBlockingStandardInputReader(void); + ssize_t read(char[], size_t); + ~NonBlockingStandardInputReader(); +}; + +NonBlockingStandardInputReader::NonBlockingStandardInputReader(void) : error_occurred(false) +{ + if (tcgetattr(STDIN_FILENO, &this->prev_termios) == -1) + { + this->error_occurred = true; + } + this->curr_termios = this->prev_termios; + this->curr_termios.c_lflag &= ~(ECHO | ICANON); + this->curr_termios.c_cc[VMIN] = 0; + this->curr_termios.c_cc[VTIME] = 0; + if (tcsetattr(STDIN_FILENO, TCSANOW, &this->curr_termios) == -1) + { + this->error_occurred = true; + } +} + +ssize_t NonBlockingStandardInputReader::read(char buf[], size_t count) +{ + return ::read(STDIN_FILENO, buf, count); +} + +NonBlockingStandardInputReader::~NonBlockingStandardInputReader() +{ + if (this->error_occurred) + { + return; + } + tcsetattr(STDIN_FILENO, TCSANOW, &this->prev_termios); +} + bool terminal_has_focus(void) { + char buf[1024] = {}; + ssize_t cnt = NonBlockingStandardInputReader().read(buf, sizeof buf / sizeof *buf); + return false; } From 7c7dea58874ea5442f5fe7199b73020f64bacc08 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 19 Apr 2026 22:47:07 +0530 Subject: [PATCH 04/23] More --- custom-prompt/focus_utils.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index b747b3c0..0683d95f 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -16,6 +16,8 @@ bool terminal_has_focus(void) #else //////////////////////////////////////////////////////////////////////// +#include + #include #include #include @@ -73,6 +75,10 @@ bool terminal_has_focus(void) { char buf[1024] = {}; ssize_t cnt = NonBlockingStandardInputReader().read(buf, sizeof buf / sizeof *buf); + if (cnt <= 0) + { + return false; + } return false; } From 5ee53047b13ac25748dc9c704632919dbac26e9d Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 19 Apr 2026 23:00:52 +0530 Subject: [PATCH 05/23] More --- custom-prompt/focus_utils.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 0683d95f..7479e38b 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -17,6 +17,7 @@ bool terminal_has_focus(void) #else //////////////////////////////////////////////////////////////////////// #include +#include #include #include @@ -74,13 +75,24 @@ NonBlockingStandardInputReader::~NonBlockingStandardInputReader() bool terminal_has_focus(void) { char buf[1024] = {}; - ssize_t cnt = NonBlockingStandardInputReader().read(buf, sizeof buf / sizeof *buf); - if (cnt <= 0) + ssize_t count = NonBlockingStandardInputReader().read(buf, sizeof buf / sizeof *buf); + if (count <= 0) { return false; } - return false; + std::string_view buf_view(buf, count); + size_t focus_in_seq_pos = buf_view.rfind("\x1b\x5bI"); + if (focus_in_seq_pos == std::string_view::npos) + { + return false; + } + size_t focus_out_seq_pos = buf_view.rfind("\x1b\x5bO"); + if (focus_out_seq_pos == std::string_view::npos) + { + return true; + } + return focus_in_seq_pos > focus_out_seq_pos; } #endif From 3850b15803d7769f0048b5a161b9bdbbce69475b Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 19 Apr 2026 23:24:45 +0530 Subject: [PATCH 06/23] Trying to fogure it out. --- custom-prompt/focus_utils.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 7479e38b..294ff991 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -16,14 +16,19 @@ bool terminal_has_focus(void) #else //////////////////////////////////////////////////////////////////////// -#include #include +#include +#include +#include #include #include #include #include "focus_utils.hh" +#include "json_logger.hh" + +static JSONLogger logger; long long unsigned get_active_wid(void) { @@ -47,6 +52,7 @@ NonBlockingStandardInputReader::NonBlockingStandardInputReader(void) : error_occ if (tcgetattr(STDIN_FILENO, &this->prev_termios) == -1) { this->error_occurred = true; + return; } this->curr_termios = this->prev_termios; this->curr_termios.c_lflag &= ~(ECHO | ICANON); @@ -55,11 +61,16 @@ NonBlockingStandardInputReader::NonBlockingStandardInputReader(void) : error_occ if (tcsetattr(STDIN_FILENO, TCSANOW, &this->curr_termios) == -1) { this->error_occurred = true; + return; } + LOG_DEBUG(logger, "Enabling focus mode" ); + std::clog << "\x1b\x5b?1004h"; } ssize_t NonBlockingStandardInputReader::read(char buf[], size_t count) { + LOG_DEBUG(logger, "Reading focus sequence" ); + std::this_thread::sleep_for(std::chrono::seconds(5)); return ::read(STDIN_FILENO, buf, count); } @@ -70,12 +81,15 @@ NonBlockingStandardInputReader::~NonBlockingStandardInputReader() return; } tcsetattr(STDIN_FILENO, TCSANOW, &this->prev_termios); + LOG_DEBUG(logger, "Disabling focus mode" ); + std::clog << "\x1b\x5b?1004l"; } bool terminal_has_focus(void) { char buf[1024] = {}; ssize_t count = NonBlockingStandardInputReader().read(buf, sizeof buf / sizeof *buf); + LOG_DEBUG(logger, "Read", {{"count", count}}); if (count <= 0) { return false; From b54f4bb4af2a54cc45ae7ea39c2430dbeddad1b4 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 00:07:02 +0530 Subject: [PATCH 07/23] Done --- custom-prompt/focus_utils.cc | 50 +++++++++++++++++++++++------------- custom-prompt/focus_utils.hh | 4 +-- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 294ff991..f561b12f 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -18,8 +18,6 @@ bool terminal_has_focus(void) #include #include -#include -#include #include #include @@ -35,19 +33,26 @@ long long unsigned get_active_wid(void) return 0; } -class NonBlockingStandardInputReader +/** + * Read focus escape sequences (and everything else mixed with them) from + * standard input in a non-blocking manner. + */ +class NonBlockingFocusEscapeSequenceReader { private: bool error_occurred; termios prev_termios, curr_termios; public: - NonBlockingStandardInputReader(void); + NonBlockingFocusEscapeSequenceReader(void); ssize_t read(char[], size_t); - ~NonBlockingStandardInputReader(); + ~NonBlockingFocusEscapeSequenceReader(); }; -NonBlockingStandardInputReader::NonBlockingStandardInputReader(void) : error_occurred(false) +/** + * Enable non-canonical mode and focus reporting. + */ +NonBlockingFocusEscapeSequenceReader::NonBlockingFocusEscapeSequenceReader(void) : error_occurred(false) { if (tcgetattr(STDIN_FILENO, &this->prev_termios) == -1) { @@ -56,45 +61,54 @@ NonBlockingStandardInputReader::NonBlockingStandardInputReader(void) : error_occ } this->curr_termios = this->prev_termios; this->curr_termios.c_lflag &= ~(ECHO | ICANON); - this->curr_termios.c_cc[VMIN] = 0; - this->curr_termios.c_cc[VTIME] = 0; + // Block until at least as many bytes as can constitute a focus escape + // sequence are available from standard input. + this->curr_termios.c_cc[VMIN] = 3; + // But not for too long. + this->curr_termios.c_cc[VTIME] = 1; if (tcsetattr(STDIN_FILENO, TCSANOW, &this->curr_termios) == -1) { this->error_occurred = true; return; } - LOG_DEBUG(logger, "Enabling focus mode" ); std::clog << "\x1b\x5b?1004h"; } -ssize_t NonBlockingStandardInputReader::read(char buf[], size_t count) +/** + * Read from standard input. + * + * @param buf Destination buffer. + * @param count Maximum number of bytes to read. + * + * @return Number of bytes read if successful, -1 otherwise. + */ +ssize_t NonBlockingFocusEscapeSequenceReader::read(char buf[], size_t count) { - LOG_DEBUG(logger, "Reading focus sequence" ); - std::this_thread::sleep_for(std::chrono::seconds(5)); return ::read(STDIN_FILENO, buf, count); } -NonBlockingStandardInputReader::~NonBlockingStandardInputReader() +/** + * Disable focus reporting and non-canonical mode. + */ +NonBlockingFocusEscapeSequenceReader::~NonBlockingFocusEscapeSequenceReader() { + std::clog << "\x1b\x5b?1004l"; if (this->error_occurred) { return; } tcsetattr(STDIN_FILENO, TCSANOW, &this->prev_termios); - LOG_DEBUG(logger, "Disabling focus mode" ); - std::clog << "\x1b\x5b?1004l"; } bool terminal_has_focus(void) { char buf[1024] = {}; - ssize_t count = NonBlockingStandardInputReader().read(buf, sizeof buf / sizeof *buf); - LOG_DEBUG(logger, "Read", {{"count", count}}); + ssize_t count = NonBlockingFocusEscapeSequenceReader().read(buf, sizeof buf / sizeof *buf); + LOG_DEBUG(logger, "Non-blocking read completed", { { "count", count }, { "buf", buf } }); if (count <= 0) { return false; } - std::string_view buf_view(buf, count); size_t focus_in_seq_pos = buf_view.rfind("\x1b\x5bI"); if (focus_in_seq_pos == std::string_view::npos) diff --git a/custom-prompt/focus_utils.hh b/custom-prompt/focus_utils.hh index b763c9c0..a25dbbbc 100644 --- a/custom-prompt/focus_utils.hh +++ b/custom-prompt/focus_utils.hh @@ -1,7 +1,7 @@ #ifndef FOCUS_UTILS_HH_ #define FOCUS_UTILS_HH_ -/* +/** * On Windows, obtain the ID of the active window. On Linux and macOS, do * nothing. * @@ -9,7 +9,7 @@ */ long long unsigned get_active_wid(void); -/* +/** * On Linux and macOS, check whether the terminal has GUI focus. On Windows, do * nothing. * From 20be70b06a3e97ad4ef93c5a2d96b9597f882627 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 00:18:39 +0530 Subject: [PATCH 08/23] Icon --- custom-prompt/custom-prompt.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index d259b383..09c64174 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -550,8 +550,10 @@ void notify_desktop(std::string_view const& last_command, int exit_code, Interva #else // Xfce Terminal (the best terminal) does not support OSC 777. Do it the // hard way. - C::notify_init(__FILE__); - C::NotifyNotification* notif = C::notify_notification_new(last_command.data(), description.data(), "terminal"); + C::notify_init("Terminal"); + C::NotifyNotification* notif = C::notify_notification_new( + last_command.data(), description.data(), exit_code == 0 ? "dialog-information" : "dialog-error" + ); C::notify_notification_show(notif, nullptr); // C::notify_uninit(); #endif From 8ecf898cd00c9f85526194fd46f08e7285527932 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 00:22:15 +0530 Subject: [PATCH 09/23] Cast --- custom-prompt/focus_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index f561b12f..76e7e06d 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -6,7 +6,7 @@ long long unsigned get_active_wid(void) { - return static_cast(GetForegroundWindow()); + return (long long unsigned)GetForegroundWindow(); } bool terminal_has_focus(void) From 53ceb25f76ecb0627f13622468c4903c343a422c Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 00:31:05 +0530 Subject: [PATCH 10/23] Wait for `BUFSIZE` bytes --- custom-prompt/focus_utils.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 76e7e06d..3909eaa5 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -26,6 +26,8 @@ bool terminal_has_focus(void) #include "focus_utils.hh" #include "json_logger.hh" +#define BUFSIZE 1024 + static JSONLogger logger; long long unsigned get_active_wid(void) @@ -61,9 +63,8 @@ NonBlockingFocusEscapeSequenceReader::NonBlockingFocusEscapeSequenceReader(void) } this->curr_termios = this->prev_termios; this->curr_termios.c_lflag &= ~(ECHO | ICANON); - // Block until at least as many bytes as can constitute a focus escape - // sequence are available from standard input. - this->curr_termios.c_cc[VMIN] = 3; + // Block until sufficiently many bytes are available from standard input. + this->curr_termios.c_cc[VMIN] = BUFSIZE; // But not for too long. this->curr_termios.c_cc[VTIME] = 1; if (tcsetattr(STDIN_FILENO, TCSANOW, &this->curr_termios) == -1) @@ -102,7 +103,7 @@ NonBlockingFocusEscapeSequenceReader::~NonBlockingFocusEscapeSequenceReader() bool terminal_has_focus(void) { - char buf[1024] = {}; + char buf[BUFSIZE] = {}; ssize_t count = NonBlockingFocusEscapeSequenceReader().read(buf, sizeof buf / sizeof *buf); LOG_DEBUG(logger, "Non-blocking read completed", { { "count", count }, { "buf", buf } }); if (count <= 0) From 391ea1db459ce1cded73098d72395d80a791ad08 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 00:41:06 +0530 Subject: [PATCH 11/23] No zero-initialisation --- custom-prompt/focus_utils.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 3909eaa5..87e9c4c6 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -26,7 +26,7 @@ bool terminal_has_focus(void) #include "focus_utils.hh" #include "json_logger.hh" -#define BUFSIZE 1024 +#define BUFSIZE 255 static JSONLogger logger; @@ -103,7 +103,7 @@ NonBlockingFocusEscapeSequenceReader::~NonBlockingFocusEscapeSequenceReader() bool terminal_has_focus(void) { - char buf[BUFSIZE] = {}; + char buf[BUFSIZE]; ssize_t count = NonBlockingFocusEscapeSequenceReader().read(buf, sizeof buf / sizeof *buf); LOG_DEBUG(logger, "Non-blocking read completed", { { "count", count }, { "buf", buf } }); if (count <= 0) From 0c68975d74536ee90de5b4098a3f8f2ecc98bc2c Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 01:00:31 +0530 Subject: [PATCH 12/23] Remove unnecessary comments [skip ci] --- custom-prompt/focus_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 87e9c4c6..0b2b1f25 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -14,7 +14,7 @@ bool terminal_has_focus(void) return false; } -#else //////////////////////////////////////////////////////////////////////// +#else #include #include From 97809a56b055a1b7c26fb8eb5bdacaa03e3777da Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 20 Apr 2026 01:07:50 +0530 Subject: [PATCH 13/23] Check more frequent case first [skip ci] --- custom-prompt/focus_utils.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 0b2b1f25..10dc420f 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -111,17 +111,17 @@ bool terminal_has_focus(void) return false; } std::string_view buf_view(buf, count); - size_t focus_in_seq_pos = buf_view.rfind("\x1b\x5bI"); - if (focus_in_seq_pos == std::string_view::npos) - { - return false; - } size_t focus_out_seq_pos = buf_view.rfind("\x1b\x5bO"); if (focus_out_seq_pos == std::string_view::npos) { return true; } - return focus_in_seq_pos > focus_out_seq_pos; + size_t focus_in_seq_pos = buf_view.rfind("\x1b\x5bI"); + if (focus_in_seq_pos == std::string_view::npos) + { + return false; + } + return focus_out_seq_pos < focus_in_seq_pos; } #endif From 2c5d01b5e7a6889e0bb477116d36783fc90c6de3 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:20:24 +0530 Subject: [PATCH 14/23] Logic for Windows (which does not work) --- .zshrc | 10 ++--- custom-prompt/custom-prompt.cc | 26 ++++--------- custom-prompt/focus_utils.cc | 69 +++++++++++++--------------------- custom-prompt/focus_utils.hh | 13 +------ 4 files changed, 41 insertions(+), 77 deletions(-) diff --git a/.zshrc b/.zshrc index 1266296a..2d78c314 100644 --- a/.zshrc +++ b/.zshrc @@ -4,16 +4,16 @@ _after_command() { local exit_code=$? - [ -z "${__begin_window+.}" ] && return + [ -z "${__begin_ts+.}" ] && return local last_command=$(history -n -1 2>/dev/null) - PS1=$(custom-zsh-prompt "$last_command" $exit_code $=__begin_window $COLUMNS $PWD $SHLVL) - unset __begin_window + PS1=$(custom-zsh-prompt "$last_command" $exit_code $__begin_ts $COLUMNS $PWD $SHLVL) + unset __begin_ts } _before_command() { - [ -n "${__begin_window+.}" ] && return - __begin_window=$(custom-zsh-prompt) + [ -n "${__begin_ts+.}" ] && return + __begin_ts=$(custom-zsh-prompt) } cfs() diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 09c64174..970ecfc6 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -632,12 +632,10 @@ void write_report(std::string_view const& last_command, int exit_code, Interval * @param last_command Most-recently run command. * @param exit_code Code with which the command exited. * @param delay Running time of the command in nanoseconds. - * @param prev_active_wid ID of the focused window when the command started. * @param columns Width of the terminal window. */ void report_command_status( - std::string_view& last_command, int exit_code, long long unsigned delay, long long unsigned prev_active_wid, - std::size_t columns + std::string_view& last_command, int exit_code, long long unsigned delay, std::size_t columns ) { LOG_DEBUG( @@ -664,18 +662,9 @@ void report_command_status( { return; } - -#ifdef _WIN32 - long long unsigned curr_active_wid = get_active_wid(); - LOG_DEBUG( - logger, "Obtained focused window details", { { "previous", prev_active_wid }, { "current", curr_active_wid } } - ); - if (prev_active_wid != curr_active_wid) -#else bool terminal_focused = terminal_has_focus(); LOG_DEBUG(logger, "Obtained focus details", { { "terminal_focused", terminal_focused } }); if (!terminal_focused) -#endif { notify_desktop(last_command, exit_code, interval); } @@ -767,7 +756,7 @@ int main_internal(int const argc, char const* argv[]) long long unsigned ts = get_timestamp(); if (argc <= 1) { - std::cout << ts << ' ' << get_active_wid() << '\n'; + std::cout << ts << '\n'; return EXIT_SUCCESS; } @@ -789,12 +778,11 @@ int main_internal(int const argc, char const* argv[]) std::string_view last_command(argv[1]); int exit_code = std::stoi(argv[2]); long long unsigned delay = ts - std::stoull(argv[3]); - long long unsigned prev_active_wid = std::stoull(argv[4]); - std::size_t columns = std::stoull(argv[5]); - report_command_status(last_command, exit_code, delay, prev_active_wid, columns); + std::size_t columns = std::stoull(argv[4]); + report_command_status(last_command, exit_code, delay, columns); - std::string_view pwd(argv[6]); - int shlvl = std::stoi(argv[7]); + std::string_view pwd(argv[5]); + int shlvl = std::stoi(argv[6]); std::string_view venv_view; char const* venv; if ((venv = getenv("VIRTUAL_ENV_PROMPT")) != nullptr) @@ -822,7 +810,7 @@ int main(int const argc, char const* argv[]) // null-terminated. if (argc == 2) { - char const* argv[] = { "custom-prompt", "[] last_command", "0", "0", "0", "79", "/", "1", nullptr }; + char const* argv[] = { "custom-prompt", "[] last_command", "0", "0", "79", "/", "1", nullptr }; int constexpr argc = sizeof argv / sizeof *argv - 1; return main_internal(argc, argv); } diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 10dc420f..a07dd877 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -1,17 +1,20 @@ +#include "focus_utils.hh" +#include "json_logger.hh" + +static JSONLogger logger; + #ifdef _WIN32 #include #include "focus_utils.hh" -long long unsigned get_active_wid(void) -{ - return (long long unsigned)GetForegroundWindow(); -} - bool terminal_has_focus(void) { - return false; + auto console_window = (long long unsigned)GetConsoleWindow(); + auto foreground_window = (long long unsigned)GetForegroundWindow(); + LOG_DEBUG(logger, "Obtained window details", {{"foreground", foreground_window}, {"console", console_window}}); + return console_window == foreground_window; } #else @@ -23,38 +26,31 @@ bool terminal_has_focus(void) #include #include -#include "focus_utils.hh" -#include "json_logger.hh" - #define BUFSIZE 255 -static JSONLogger logger; - long long unsigned get_active_wid(void) { return 0; } /** - * Read focus escape sequences (and everything else mixed with them) from - * standard input in a non-blocking manner. + * Temporarily modify standard input to allow non-blocking reads. */ -class NonBlockingFocusEscapeSequenceReader +class NonBlockingStandardInputGuard { private: bool error_occurred; termios prev_termios, curr_termios; public: - NonBlockingFocusEscapeSequenceReader(void); - ssize_t read(char[], size_t); - ~NonBlockingFocusEscapeSequenceReader(); + NonBlockingStandardInputGuard(void); + ~NonBlockingStandardInputGuard(); }; /** - * Enable non-canonical mode and focus reporting. + * Enable non-canonical mode. */ -NonBlockingFocusEscapeSequenceReader::NonBlockingFocusEscapeSequenceReader(void) : error_occurred(false) +NonBlockingStandardInputGuard::NonBlockingStandardInputGuard(void) : error_occurred(false) { if (tcgetattr(STDIN_FILENO, &this->prev_termios) == -1) { @@ -70,42 +66,31 @@ NonBlockingFocusEscapeSequenceReader::NonBlockingFocusEscapeSequenceReader(void) if (tcsetattr(STDIN_FILENO, TCSANOW, &this->curr_termios) == -1) { this->error_occurred = true; - return; } - std::clog << "\x1b\x5b?1004h"; -} - -/** - * Read from standard input. - * - * @param buf Destination buffer. - * @param count Maximum number of bytes to read. - * - * @return Number of bytes read if successful, -1 otherwise. - */ -ssize_t NonBlockingFocusEscapeSequenceReader::read(char buf[], size_t count) -{ - return ::read(STDIN_FILENO, buf, count); } /** - * Disable focus reporting and non-canonical mode. + * Disable non-canonical mode. */ -NonBlockingFocusEscapeSequenceReader::~NonBlockingFocusEscapeSequenceReader() +NonBlockingStandardInputGuard::~NonBlockingStandardInputGuard() { - std::clog << "\x1b\x5b?1004l"; - if (this->error_occurred) + if (!this->error_occurred) { - return; - } tcsetattr(STDIN_FILENO, TCSANOW, &this->prev_termios); + } } bool terminal_has_focus(void) { char buf[BUFSIZE]; - ssize_t count = NonBlockingFocusEscapeSequenceReader().read(buf, sizeof buf / sizeof *buf); - LOG_DEBUG(logger, "Non-blocking read completed", { { "count", count }, { "buf", buf } }); + ssize_t count; + { + NonBlockingStandardInputGuard _; + // Enable and immediately disable focus reporting. + std::clog << "\x1b\x5b?1004h" << "\x1b\x5b?1004l"; + count = read(STDIN_FILENO, buf, sizeof buf / sizeof *buf); + } + LOG_DEBUG(logger, "Completed non-blocking standard input read", { { "count", count } }); if (count <= 0) { return false; diff --git a/custom-prompt/focus_utils.hh b/custom-prompt/focus_utils.hh index a25dbbbc..9bf23c63 100644 --- a/custom-prompt/focus_utils.hh +++ b/custom-prompt/focus_utils.hh @@ -2,18 +2,9 @@ #define FOCUS_UTILS_HH_ /** - * On Windows, obtain the ID of the active window. On Linux and macOS, do - * nothing. + * Check whether the terminal has GUI focus. * - * @return Active window ID or unspecified value (as described above). - */ -long long unsigned get_active_wid(void); - -/** - * On Linux and macOS, check whether the terminal has GUI focus. On Windows, do - * nothing. - * - * @return Focus state or unspecified value (as described above). + * @return Focus state. */ bool terminal_has_focus(void); From 8410d4768719d4520971bb7a5b041b837e79bbbb Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:50:21 +0530 Subject: [PATCH 15/23] Check window class --- custom-prompt/focus_utils.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index a07dd877..84e38821 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -5,16 +5,24 @@ static JSONLogger logger; #ifdef _WIN32 +#include + #include #include "focus_utils.hh" bool terminal_has_focus(void) { - auto console_window = (long long unsigned)GetConsoleWindow(); - auto foreground_window = (long long unsigned)GetForegroundWindow(); - LOG_DEBUG(logger, "Obtained window details", {{"foreground", foreground_window}, {"console", console_window}}); - return console_window == foreground_window; + HWND foreground_window = GetForegroundWindow(); + TCHAR class_name[64]; + int class_name_len = GetClassName(foreground_window, class_name, sizeof class_name / sizeof *class_name); + LOG_DEBUG(logger, "Obtained window details", {{"class_name_len", class_name_len} }); + if(class_name_len == 0){ + return false; + } + // I use WezTerm on Windows because it supports OSC 777. Checking whether + // a Wezterm window is active is reasonable for me. + return std::string_view(class_name) == "org.wezfurlong.wezterm"; } #else From edf40d6706ca8b7b15a420c30b6c8f1ed6037764 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:52:32 +0530 Subject: [PATCH 16/23] Logs [skip ci] --- custom-prompt/focus_utils.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 84e38821..cc323a45 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -16,7 +16,7 @@ bool terminal_has_focus(void) HWND foreground_window = GetForegroundWindow(); TCHAR class_name[64]; int class_name_len = GetClassName(foreground_window, class_name, sizeof class_name / sizeof *class_name); - LOG_DEBUG(logger, "Obtained window details", {{"class_name_len", class_name_len} }); + LOG_DEBUG(logger, "Read active window", {{"class_name_len", class_name_len} }); if(class_name_len == 0){ return false; } @@ -98,7 +98,7 @@ bool terminal_has_focus(void) std::clog << "\x1b\x5b?1004h" << "\x1b\x5b?1004l"; count = read(STDIN_FILENO, buf, sizeof buf / sizeof *buf); } - LOG_DEBUG(logger, "Completed non-blocking standard input read", { { "count", count } }); + LOG_DEBUG(logger, "Read non-blocking standard input", { { "count", count } }); if (count <= 0) { return false; From 19b50fdaa9304ff83f809a4ff4a31bea4fd4ee24 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:59:30 +0530 Subject: [PATCH 17/23] Better `string_view` construction [skip ci] --- custom-prompt/focus_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index cc323a45..69773ace 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -22,7 +22,7 @@ bool terminal_has_focus(void) } // I use WezTerm on Windows because it supports OSC 777. Checking whether // a Wezterm window is active is reasonable for me. - return std::string_view(class_name) == "org.wezfurlong.wezterm"; + return std::string_view(class_name, class_name_len) == "org.wezfurlong.wezterm"; } #else From 4461a1932a25cde69c6996207e2537f7015e89d1 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:10:13 +0530 Subject: [PATCH 18/23] Generic Windows strings [skip ci] --- custom-prompt/focus_utils.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 69773ace..a193173a 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -5,8 +5,7 @@ static JSONLogger logger; #ifdef _WIN32 -#include - +#include #include #include "focus_utils.hh" @@ -22,7 +21,7 @@ bool terminal_has_focus(void) } // I use WezTerm on Windows because it supports OSC 777. Checking whether // a Wezterm window is active is reasonable for me. - return std::string_view(class_name, class_name_len) == "org.wezfurlong.wezterm"; + return _tcscmp(class_name, _T("org.wezfurlong.wezterm")) == 0; } #else From 50ea8aa394583a3d4c9e00da46a4ef76d4ed074b Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:11:13 +0530 Subject: [PATCH 19/23] Remove unnecessary import [skip ci] --- custom-prompt/focus_utils.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index a193173a..7932cd90 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -8,8 +8,6 @@ static JSONLogger logger; #include #include -#include "focus_utils.hh" - bool terminal_has_focus(void) { HWND foreground_window = GetForegroundWindow(); From 61527878bebfeac61b3c5f92a598546a1ff5a54f Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:12:35 +0530 Subject: [PATCH 20/23] Remove unnecessary function [skip ci] --- custom-prompt/focus_utils.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 7932cd90..f4af54cb 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -33,11 +33,6 @@ bool terminal_has_focus(void) #define BUFSIZE 255 -long long unsigned get_active_wid(void) -{ - return 0; -} - /** * Temporarily modify standard input to allow non-blocking reads. */ From 8b5354a3be047c2dc2db72d82635456d061d231a Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:15:34 +0530 Subject: [PATCH 21/23] Bash changes [skip ci] --- .bash_aliases | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.bash_aliases b/.bash_aliases index 398fbffa..2110a4b9 100644 --- a/.bash_aliases +++ b/.bash_aliases @@ -131,8 +131,8 @@ command grep -Fiq microsoft /proc/version && . $HOME/.bash_aliases_wsl.bash # executed. _before_command() { - [ -n "${__begin_window+.}" ] && return - __begin_window=$(custom-bash-prompt) + [ -n "${__begin_ts+.}" ] && return + __begin_ts=$(custom-bash-prompt) } # Post-command for command timing. It will be called just before the prompt is @@ -140,10 +140,10 @@ _before_command() _after_command() { local exit_code=$? - [ -z "${__begin_window+.}" ] && return + [ -z "${__begin_ts+.}" ] && return local last_command=$(history 1) - PS1=$(custom-bash-prompt "$last_command" $exit_code $__begin_window $COLUMNS "$PWD" $SHLVL) - unset __begin_window + PS1=$(custom-bash-prompt "$last_command" $exit_code $__begin_ts $COLUMNS "$PWD" $SHLVL) + unset __begin_ts } trap _before_command DEBUG From 52c85f9d314bf5644f8a0d9adcf4ba52325a5957 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:21:45 +0530 Subject: [PATCH 22/23] Formatted --- custom-prompt/custom-prompt.cc | 2 +- custom-prompt/focus_utils.cc | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 970ecfc6..81356d28 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -635,7 +635,7 @@ void write_report(std::string_view const& last_command, int exit_code, Interval * @param columns Width of the terminal window. */ void report_command_status( - std::string_view& last_command, int exit_code, long long unsigned delay, std::size_t columns + std::string_view& last_command, int exit_code, long long unsigned delay, std::size_t columns ) { LOG_DEBUG( diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index f4af54cb..6f15116e 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -13,8 +13,9 @@ bool terminal_has_focus(void) HWND foreground_window = GetForegroundWindow(); TCHAR class_name[64]; int class_name_len = GetClassName(foreground_window, class_name, sizeof class_name / sizeof *class_name); - LOG_DEBUG(logger, "Read active window", {{"class_name_len", class_name_len} }); - if(class_name_len == 0){ + LOG_DEBUG(logger, "Read active window", { { "class_name_len", class_name_len } }); + if (class_name_len == 0) + { return false; } // I use WezTerm on Windows because it supports OSC 777. Checking whether @@ -76,7 +77,7 @@ NonBlockingStandardInputGuard::~NonBlockingStandardInputGuard() { if (!this->error_occurred) { - tcsetattr(STDIN_FILENO, TCSANOW, &this->prev_termios); + tcsetattr(STDIN_FILENO, TCSANOW, &this->prev_termios); } } @@ -85,10 +86,10 @@ bool terminal_has_focus(void) char buf[BUFSIZE]; ssize_t count; { - NonBlockingStandardInputGuard _; - // Enable and immediately disable focus reporting. - std::clog << "\x1b\x5b?1004h" << "\x1b\x5b?1004l"; - count = read(STDIN_FILENO, buf, sizeof buf / sizeof *buf); + NonBlockingStandardInputGuard _; + // Enable and immediately disable focus reporting. + std::clog << "\x1b\x5b?1004h\x1b\x5b?1004l"; + count = read(STDIN_FILENO, buf, sizeof buf / sizeof *buf); } LOG_DEBUG(logger, "Read non-blocking standard input", { { "count", count } }); if (count <= 0) From b528497a8adccac2f7ef2d3e6ae55ad00cd56ab3 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:34:36 +0530 Subject: [PATCH 23/23] Comment --- custom-prompt/focus_utils.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/custom-prompt/focus_utils.cc b/custom-prompt/focus_utils.cc index 6f15116e..30058eaa 100644 --- a/custom-prompt/focus_utils.cc +++ b/custom-prompt/focus_utils.cc @@ -18,8 +18,9 @@ bool terminal_has_focus(void) { return false; } - // I use WezTerm on Windows because it supports OSC 777. Checking whether - // a Wezterm window is active is reasonable for me. + // I use WezTerm on Windows because it supports OSC 777; I never open more + // than one window. Hence, checking whether a Wezterm window is active is + // sufficient for me. return _tcscmp(class_name, _T("org.wezfurlong.wezterm")) == 0; }