mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-05 07:29:49 +00:00
LibVT+Terminal: Support hyperlinks in the terminal :^)
We now support basic hyperlinking in the terminal with <OSC>;8;;URL<ST> Links are opened via LaunchServer on Ctrl+LeftMouse.
This commit is contained in:
parent
427863f275
commit
f596b12a04
|
@ -3,6 +3,6 @@ OBJS = \
|
|||
|
||||
PROGRAM = Terminal
|
||||
|
||||
LIB_DEPS = GUI Gfx VT IPC Protocol Core
|
||||
LIB_DEPS = GUI Gfx VT Desktop IPC Protocol Core
|
||||
|
||||
include ../../Makefile.common
|
||||
|
|
|
@ -190,7 +190,7 @@ int main(int argc, char** argv)
|
|||
|
||||
GUI::Application app(argc, argv);
|
||||
|
||||
if (pledge("stdio tty rpath accept cpath wpath shared_buffer proc exec", nullptr) < 0) {
|
||||
if (pledge("stdio tty rpath accept cpath wpath shared_buffer proc exec unix", nullptr) < 0) {
|
||||
perror("pledge");
|
||||
return 1;
|
||||
}
|
||||
|
@ -313,6 +313,11 @@ int main(int argc, char** argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (unveil("/tmp/portal/launch", "rw") < 0) {
|
||||
perror("unveil");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unveil(config->file_name().characters(), "rwc")) {
|
||||
perror("unveil");
|
||||
return 1;
|
||||
|
|
|
@ -19,6 +19,6 @@ OBJS = \
|
|||
|
||||
PROGRAM = HackStudio
|
||||
|
||||
LIB_DEPS = GUI Web TextCodec VT Protocol Markdown Gfx IPC Thread Pthread Core JS Debug
|
||||
LIB_DEPS = GUI Web TextCodec VT Desktop Protocol Markdown Gfx IPC Thread Pthread Core JS Debug
|
||||
|
||||
include ../../Makefile.common
|
||||
|
|
|
@ -61,7 +61,8 @@ void Terminal::Line::set_length(u16 new_length)
|
|||
memset(new_characters, ' ', new_length);
|
||||
if (characters && attributes) {
|
||||
memcpy(new_characters, characters, min(m_length, new_length));
|
||||
memcpy(new_attributes, attributes, min(m_length, new_length) * sizeof(Attribute));
|
||||
for (size_t i = 0; i < min(m_length, new_length); ++i)
|
||||
new_attributes[i] = attributes[i];
|
||||
}
|
||||
delete[] characters;
|
||||
delete[] attributes;
|
||||
|
@ -605,6 +606,11 @@ void Terminal::execute_xterm_command()
|
|||
case 2:
|
||||
m_client.set_window_title(params[1]);
|
||||
break;
|
||||
case 8:
|
||||
m_current_attribute.href = params[2];
|
||||
// FIXME: Respect the provided ID
|
||||
m_current_attribute.href_id = String::format("%u", m_next_href_id++);
|
||||
break;
|
||||
default:
|
||||
unimplemented_xterm_escape();
|
||||
break;
|
||||
|
@ -1076,4 +1082,16 @@ void Terminal::execute_hashtag(u8 hashtag)
|
|||
}
|
||||
}
|
||||
|
||||
Attribute Terminal::attribute_at(const Position& position) const
|
||||
{
|
||||
if (!position.is_valid())
|
||||
return {};
|
||||
if (position.row() >= static_cast<int>(m_lines.size()))
|
||||
return {};
|
||||
auto& line = this->line(position.row());
|
||||
if (position.column() >= line.m_length)
|
||||
return {};
|
||||
return line.attributes[position.column()];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ struct Attribute {
|
|||
u8 foreground_color;
|
||||
u8 background_color;
|
||||
|
||||
String href;
|
||||
String href_id;
|
||||
|
||||
enum Flags : u8 {
|
||||
NoAttributes = 0x00,
|
||||
Bold = 0x01,
|
||||
|
@ -137,6 +140,8 @@ public:
|
|||
|
||||
void inject_string(const StringView&);
|
||||
|
||||
Attribute attribute_at(const Position&) const;
|
||||
|
||||
private:
|
||||
typedef Vector<unsigned, 4> ParamVector;
|
||||
|
||||
|
@ -204,6 +209,8 @@ private:
|
|||
|
||||
Attribute m_current_attribute;
|
||||
|
||||
u32 m_next_href_id { 0 };
|
||||
|
||||
void execute_escape_sequence(u8 final);
|
||||
void execute_xterm_command();
|
||||
void execute_hashtag(u8);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <AK/Utf8View.h>
|
||||
#include <Kernel/KeyCode.h>
|
||||
#include <LibCore/MimeData.h>
|
||||
#include <LibDesktop/Launcher.h>
|
||||
#include <LibGUI/Action.h>
|
||||
#include <LibGUI/Application.h>
|
||||
#include <LibGUI/Clipboard.h>
|
||||
|
@ -371,7 +372,11 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
|||
if (!has_only_one_background_color || should_reverse_fill_for_cursor_or_selection) {
|
||||
painter.clear_rect(cell_rect, lookup_color(should_reverse_fill_for_cursor_or_selection ? attribute.foreground_color : attribute.background_color).with_alpha(m_opacity));
|
||||
}
|
||||
if (attribute.flags & VT::Attribute::Underline)
|
||||
|
||||
bool should_paint_underline = attribute.flags & VT::Attribute::Underline
|
||||
|| (!m_hovered_href.is_empty() && m_hovered_href_id == attribute.href_id);
|
||||
|
||||
if (should_paint_underline)
|
||||
painter.draw_line(cell_rect.bottom_left(), cell_rect.bottom_right(), lookup_color(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color));
|
||||
}
|
||||
|
||||
|
@ -586,6 +591,15 @@ void TerminalWidget::copy()
|
|||
|
||||
void TerminalWidget::mousedown_event(GUI::MouseEvent& event)
|
||||
{
|
||||
if (event.modifiers() == Mod_Ctrl && event.button() == GUI::MouseButton::Left) {
|
||||
auto attribute = m_terminal.attribute_at(buffer_position_at(event.position()));
|
||||
if (!attribute.href.is_empty()) {
|
||||
dbg() << "Open URL: _" << attribute.href << "_";
|
||||
Desktop::Launcher::open(attribute.href);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.button() == GUI::MouseButton::Left) {
|
||||
if (m_triple_click_timer.is_valid() && m_triple_click_timer.elapsed() < 250) {
|
||||
int start_column = 0;
|
||||
|
@ -609,11 +623,20 @@ void TerminalWidget::mousedown_event(GUI::MouseEvent& event)
|
|||
|
||||
void TerminalWidget::mousemove_event(GUI::MouseEvent& event)
|
||||
{
|
||||
auto position = buffer_position_at(event.position());
|
||||
|
||||
auto attribute = m_terminal.attribute_at(position);
|
||||
if (attribute.href_id != m_hovered_href_id) {
|
||||
m_hovered_href_id = attribute.href_id;
|
||||
m_hovered_href = attribute.href;
|
||||
update();
|
||||
}
|
||||
|
||||
if (!(event.buttons() & GUI::MouseButton::Left))
|
||||
return;
|
||||
|
||||
auto old_selection_end = m_selection_end;
|
||||
m_selection_end = buffer_position_at(event.position());
|
||||
m_selection_end = position;
|
||||
if (old_selection_end != m_selection_end)
|
||||
update();
|
||||
}
|
||||
|
|
|
@ -129,6 +129,9 @@ private:
|
|||
VT::Position m_selection_start;
|
||||
VT::Position m_selection_end;
|
||||
|
||||
String m_hovered_href;
|
||||
String m_hovered_href_id;
|
||||
|
||||
bool m_should_beep { false };
|
||||
bool m_belling { false };
|
||||
bool m_alt_key_held { false };
|
||||
|
|
Loading…
Reference in a new issue