Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/String.h>
30#include <LibCore/ConfigFile.h>
31#include <LibCore/ElapsedTimer.h>
32#include <LibCore/Notifier.h>
33#include <LibCore/Timer.h>
34#include <LibGUI/Frame.h>
35#include <LibGfx/Bitmap.h>
36#include <LibGfx/Rect.h>
37#include <LibVT/Terminal.h>
38
39class TerminalWidget final : public GUI::Frame
40 , public VT::TerminalClient {
41 C_OBJECT(TerminalWidget)
42public:
43 TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<Core::ConfigFile> config);
44 virtual ~TerminalWidget() override;
45
46 void set_pty_master_fd(int fd);
47 void inject_string(const StringView& string)
48 {
49 m_terminal.inject_string(string);
50 flush_dirty_lines();
51 }
52
53 void create_window();
54
55 void flush_dirty_lines();
56 void force_repaint();
57
58 void apply_size_increments_to_window(GUI::Window&);
59
60 const Gfx::Font& bold_font() const { return *m_bold_font; }
61
62 void set_opacity(u8);
63 float opacity() { return m_opacity; };
64 bool should_beep() { return m_should_beep; }
65 void set_should_beep(bool sb) { m_should_beep = sb; };
66
67 RefPtr<Core::ConfigFile> config() const { return m_config; }
68
69 bool has_selection() const;
70 bool selection_contains(const VT::Position&) const;
71 String selected_text() const;
72 VT::Position buffer_position_at(const Gfx::Point&) const;
73 VT::Position normalized_selection_start() const;
74 VT::Position normalized_selection_end() const;
75
76 bool is_scrollable() const;
77
78 GUI::Action& copy_action() { return *m_copy_action; }
79 GUI::Action& paste_action() { return *m_paste_action; }
80
81 void copy();
82 void paste();
83
84 virtual bool accepts_focus() const override { return true; }
85
86 Function<void(const StringView&)> on_title_change;
87 Function<void()> on_command_exit;
88
89private:
90 // ^GUI::Widget
91 virtual void event(Core::Event&) override;
92 virtual void paint_event(GUI::PaintEvent&) override;
93 virtual void resize_event(GUI::ResizeEvent&) override;
94 virtual void keydown_event(GUI::KeyEvent&) override;
95 virtual void keyup_event(GUI::KeyEvent&) override;
96 virtual void mousedown_event(GUI::MouseEvent&) override;
97 virtual void mousemove_event(GUI::MouseEvent&) override;
98 virtual void mousewheel_event(GUI::MouseEvent&) override;
99 virtual void doubleclick_event(GUI::MouseEvent&) override;
100 virtual void focusin_event(Core::Event&) override;
101 virtual void focusout_event(Core::Event&) override;
102 virtual void context_menu_event(GUI::ContextMenuEvent&) override;
103 virtual void drop_event(GUI::DropEvent&) override;
104 virtual void did_change_font() override;
105
106 // ^TerminalClient
107 virtual void beep() override;
108 virtual void set_window_title(const StringView&) override;
109 virtual void terminal_did_resize(u16 columns, u16 rows) override;
110 virtual void terminal_history_changed() override;
111 virtual void emit_char(u8) override;
112
113 void set_logical_focus(bool);
114
115 Gfx::Rect glyph_rect(u16 row, u16 column);
116 Gfx::Rect row_rect(u16 row);
117
118 void update_cursor();
119 void invalidate_cursor();
120
121 void relayout(const Gfx::Size&);
122
123 Gfx::Size compute_base_size() const;
124 int first_selection_column_on_row(int row) const;
125 int last_selection_column_on_row(int row) const;
126
127 VT::Terminal m_terminal;
128
129 VT::Position m_selection_start;
130 VT::Position m_selection_end;
131
132 bool m_should_beep { false };
133 bool m_belling { false };
134 bool m_alt_key_held { false };
135 bool m_rectangle_selection { false };
136
137 int m_pixel_width { 0 };
138 int m_pixel_height { 0 };
139
140 int m_inset { 2 };
141 int m_line_spacing { 4 };
142 int m_line_height { 0 };
143
144 int m_ptm_fd { -1 };
145
146 bool m_has_logical_focus { false };
147
148 RefPtr<Core::Notifier> m_notifier;
149
150 u8 m_opacity { 255 };
151 bool m_needs_background_fill { true };
152 bool m_cursor_blink_state { true };
153 bool m_automatic_size_policy { false };
154
155 RefPtr<Gfx::Font> m_bold_font;
156
157 int m_glyph_width { 0 };
158
159 RefPtr<Core::Timer> m_cursor_blink_timer;
160 RefPtr<Core::Timer> m_visual_beep_timer;
161 RefPtr<Core::ConfigFile> m_config;
162
163 RefPtr<GUI::ScrollBar> m_scrollbar;
164
165 RefPtr<GUI::Action> m_copy_action;
166 RefPtr<GUI::Action> m_paste_action;
167
168 RefPtr<GUI::Menu> m_context_menu;
169
170 Core::ElapsedTimer m_triple_click_timer;
171};