forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
259 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright (c) 2023, the SerenityOS developers. | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include "TerminalChangeListener.h" | ||
#include <LibGUI/Window.h> | ||
|
||
void TerminalChangeListener::config_bool_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, bool value) | ||
{ | ||
VERIFY(domain == "Terminal"); | ||
|
||
if (group == "Terminal") { | ||
if (key == "ShowScrollBar") | ||
m_parent_terminal.set_show_scrollbar(value); | ||
else if (key == "ConfirmClose" && on_confirm_close_changed) | ||
on_confirm_close_changed(value); | ||
} else if (group == "Cursor" && key == "Blinking") { | ||
m_parent_terminal.set_cursor_blinking(value); | ||
} | ||
} | ||
|
||
void TerminalChangeListener::config_string_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, DeprecatedString const& value) | ||
{ | ||
VERIFY(domain == "Terminal"); | ||
|
||
if (group == "Window" && key == "Bell") { | ||
auto bell_mode = VT::TerminalWidget::BellMode::Visible; | ||
if (value == "AudibleBeep") | ||
bell_mode = VT::TerminalWidget::BellMode::AudibleBeep; | ||
if (value == "Visible") | ||
bell_mode = VT::TerminalWidget::BellMode::Visible; | ||
if (value == "Disabled") | ||
bell_mode = VT::TerminalWidget::BellMode::Disabled; | ||
m_parent_terminal.set_bell_mode(bell_mode); | ||
} else if (group == "Text" && key == "Font") { | ||
auto font = Gfx::FontDatabase::the().get_by_name(value); | ||
if (font.is_null()) | ||
font = Gfx::FontDatabase::default_fixed_width_font(); | ||
m_parent_terminal.set_font_and_resize_to_fit(*font); | ||
m_parent_terminal.apply_size_increments_to_window(*m_parent_terminal.window()); | ||
m_parent_terminal.window()->resize(m_parent_terminal.size()); | ||
} else if (group == "Cursor" && key == "Shape") { | ||
auto cursor_shape = VT::TerminalWidget::parse_cursor_shape(value).value_or(VT::CursorShape::Block); | ||
m_parent_terminal.set_cursor_shape(cursor_shape); | ||
} | ||
} | ||
|
||
void TerminalChangeListener::config_i32_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, i32 value) | ||
{ | ||
VERIFY(domain == "Terminal"); | ||
|
||
if (group == "Terminal" && key == "MaxHistorySize") { | ||
m_parent_terminal.set_max_history_size(value); | ||
} else if (group == "Window" && key == "Opacity") { | ||
m_parent_terminal.set_opacity(value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright (c) 2023, the SerenityOS developers. | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <LibGfx/Font/FontDatabase.h> | ||
#include <LibConfig/Listener.h> | ||
#include <LibVT/TerminalWidget.h> | ||
|
||
class TerminalChangeListener : public Config::Listener { | ||
public: | ||
TerminalChangeListener(VT::TerminalWidget& parent_terminal) | ||
: m_parent_terminal(parent_terminal) | ||
{ | ||
} | ||
|
||
virtual void config_bool_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, bool value) override; | ||
virtual void config_string_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, DeprecatedString const& value) override; | ||
virtual void config_i32_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, i32 value) override; | ||
|
||
Function<void(bool)> on_confirm_close_changed; | ||
|
||
private: | ||
VT::TerminalWidget& m_parent_terminal; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright (c) 2023, the SerenityOS developers. | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include "TerminalUtilities.h" | ||
#include <AK/Format.h> | ||
#include <AK/FixedArray.h> | ||
#include <AK/Try.h> | ||
#include <AK/Vector.h> | ||
#include <LibConfig/Client.h> | ||
#include <LibCore/System.h> | ||
#include <LibFileSystem/FileSystem.h> | ||
#include <assert.h> | ||
#include <errno.h> | ||
#include <pty.h> | ||
#include <pwd.h> | ||
#include <signal.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/wait.h> | ||
#include <unistd.h> | ||
|
||
void utmp_update(DeprecatedString const& tty, pid_t pid, bool create) | ||
{ | ||
int utmpupdate_pid = fork(); | ||
if (utmpupdate_pid < 0) { | ||
perror("fork"); | ||
return; | ||
} | ||
if (utmpupdate_pid == 0) { | ||
// Be careful here! Because fork() only clones one thread it's | ||
// possible that we deadlock on anything involving a mutex, | ||
// including the heap! So resort to low-level APIs | ||
char pid_str[32]; | ||
snprintf(pid_str, sizeof(pid_str), "%d", pid); | ||
execl("/bin/utmpupdate", "/bin/utmpupdate", "-f", "Terminal", "-p", pid_str, (create ? "-c" : "-d"), tty.characters(), nullptr); | ||
} else { | ||
wait_again: | ||
int status = 0; | ||
if (waitpid(utmpupdate_pid, &status, 0) < 0) { | ||
int err = errno; | ||
if (err == EINTR) | ||
goto wait_again; | ||
perror("waitpid"); | ||
return; | ||
} | ||
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) | ||
dbgln("Terminal: utmpupdate exited with status {}", WEXITSTATUS(status)); | ||
else if (WIFSIGNALED(status)) | ||
dbgln("Terminal: utmpupdate exited due to unhandled signal {}", WTERMSIG(status)); | ||
} | ||
} | ||
|
||
ErrorOr<void> run_command(DeprecatedString command, bool keep_open) | ||
{ | ||
DeprecatedString shell = "/bin/Shell"; | ||
auto* pw = getpwuid(getuid()); | ||
if (pw && pw->pw_shell) { | ||
shell = pw->pw_shell; | ||
} | ||
endpwent(); | ||
|
||
Vector<StringView> arguments; | ||
arguments.append(shell); | ||
if (!command.is_empty()) { | ||
if (keep_open) | ||
arguments.append("--keep-open"sv); | ||
arguments.append("-c"sv); | ||
arguments.append(command); | ||
} | ||
auto env = TRY(FixedArray<StringView>::create({ "TERM=xterm"sv, "PAGER=more"sv, "PATH="sv DEFAULT_PATH_SV })); | ||
TRY(Core::System::exec(shell, arguments, Core::System::SearchInPath::No, env.span())); | ||
VERIFY_NOT_REACHED(); | ||
} | ||
|
||
ErrorOr<NonnullRefPtr<VT::TerminalWidget>> create_and_setup_terminal_widget() | ||
{ | ||
int ptm_fd; | ||
pid_t shell_pid = forkpty(&ptm_fd, nullptr, nullptr, nullptr); | ||
if (shell_pid == 0) { | ||
MUST(run_command(Config::read_string("Terminal"sv, "Startup"sv, "Command"sv, ""sv), false)); | ||
VERIFY_NOT_REACHED(); | ||
} | ||
|
||
auto ptsname = TRY(Core::System::ptsname(ptm_fd)); | ||
utmp_update(ptsname, shell_pid, true); | ||
|
||
auto terminal = TRY(VT::TerminalWidget::try_create(ptm_fd, true)); | ||
|
||
return terminal; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright (c) 2023, the SerenityOS developers. | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <AK/Error.h> | ||
#include <AK/DeprecatedString.h> | ||
#include <AK/StringView.h> | ||
#include <LibVT/TerminalWidget.h> | ||
#include <sys/types.h> | ||
|
||
void utmp_update(DeprecatedString const& tty, pid_t pid, bool create); | ||
|
||
ErrorOr<void> run_command(DeprecatedString command, bool keep_open); | ||
|
||
ErrorOr<NonnullRefPtr<VT::TerminalWidget>> create_and_setup_terminal_widget(); |
Oops, something went wrong.