// Display images inside a terminal
// Copyright (C) 2023 JustKidding
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
#include "tmux.hpp"
#include "os.hpp"
#include "util.hpp"
#include
#include
#include
#include
constexpr auto session_hooks = std::to_array(
{"session-window-changed", "client-detached", "window-layout-changed"});
constexpr auto global_hooks = std::to_array(
{"client-session-changed"});
auto tmux::get_session_id() -> std::string
{
const auto cmd = fmt::format("tmux display -p -F '#{{session_id}}' -t {}", tmux::get_pane());
return os::exec(cmd);
}
auto tmux::is_used() -> bool
{
return !tmux::get_pane().empty();
}
auto tmux::is_window_focused() -> bool
{
const auto cmd = fmt::format("tmux display -p -F '#{{session_attached}},#{{window_active}},#{{pane_in_mode}}' -t {}", tmux::get_pane());
return os::exec(cmd) == "1,1,0";
}
auto tmux::get_pane() -> std::string
{
return os::getenv("TMUX_PANE").value_or("");
}
auto tmux::get_client_pids() -> std::optional>
{
if (!tmux::is_used()) {
return {};
}
if (!tmux::is_window_focused()) {
return {};
}
std::vector pids;
const auto cmd = fmt::format("tmux list-clients -F '#{{client_pid}}' -t {}", tmux::get_pane());
const auto output = os::exec(cmd);
for (const auto &line : util::str_split(output, "\n")) {
pids.push_back(std::stoi(line));
}
return pids;
}
auto tmux::get_offset() -> std::pair
{
if (!tmux::is_used()) {
return std::make_pair(0, 0);
}
const auto [p_x, p_y] = tmux::get_pane_offset();
const auto s_y = tmux::get_statusbar_offset();
return std::make_pair(p_x, p_y + s_y);
}
auto tmux::get_pane_offset() -> std::pair
{
const auto cmd = fmt::format(R"(tmux display -p -F '#{{pane_top}},#{{pane_left}},
#{{pane_bottom}},#{{pane_right}},
#{{window_height}},#{{window_width}}' -t {})",
tmux::get_pane());
const auto output = util::str_split(os::exec(cmd), ",");
return std::make_pair(std::stoi(output.at(1)), std::stoi(output.at(0)));
}
auto tmux::get_statusbar_offset() -> int
{
const std::string cmd = "tmux display -p '#{status},#{status-position}'";
const auto output = util::str_split(os::exec(cmd), ",");
if (output.at(1) != "top" || output.at(0) == "off") {
return 0;
}
if (output.at(0) == "on") {
return 1;
}
return std::stoi(output.at(0));
}
void tmux::handle_hook(const std::string_view hook, int pid)
{
const auto msg = fmt::format(R"({{"action":"tmux","hook":"{}"}})", hook);
const auto endpoint = util::get_socket_path(pid);
util::send_socket_message(msg, endpoint);
}
void tmux::register_hooks()
{
if (!tmux::is_used()) {
return;
}
for (const auto &hook : session_hooks) {
std::string cmd = fmt::format(R"(tmux set-hook -t {0} {1} "run-shell 'ueberzugpp tmux {1} {2}'")", tmux::get_pane(), hook, os::get_pid());
os::exec(cmd);
}
for (const auto &hook : global_hooks) {
std::string cmd = fmt::format(R"(tmux set-hook -g {0} "run-shell 'ueberzugpp tmux {0} {1}'")", hook, os::get_pid());
os::exec(cmd);
}
}
void tmux::unregister_hooks()
{
if (!tmux::is_used()) {
return;
}
for (const auto &hook : session_hooks) {
const auto cmd = fmt::format("tmux set-hook -u -t {} {}", tmux::get_pane(), hook);
os::exec(cmd);
}
for (const auto &hook : global_hooks) {
const auto cmd = fmt::format("tmux set-hook -gu {}", hook);
os::exec(cmd);
}
}