mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-22 17:50:25 +01:00
a849423096
Rewrites the Terminal class as a GDExtension to be used directly in Godot without a terminal.gd proxy. Breaks a lot of things in its current state (e.g. signals and other functions have not be implemented yet), but does add support for transparent colors and true color inversion. It also seems to be about 4x faster (FPS-wise) than the old version with some basic stress testing. Old source code has been moved to a different directory to be copied over and/or rewritten piece by piece.
164 lines
4.5 KiB
C++
164 lines
4.5 KiB
C++
// SPDX-FileCopyrightText: 2021-2023 Leroy Hopson <godot-xterm@leroy.geek.nz>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#ifndef GODOT_XTERM_TERMINAL_H
|
|
#define GODOT_XTERM_TERMINAL_H
|
|
|
|
#include <godot_cpp/classes/control.hpp>
|
|
#include <godot_cpp/classes/font.hpp>
|
|
#include <godot_cpp/classes/input_event.hpp>
|
|
#include <godot_cpp/classes/input_event_key.hpp>
|
|
#include <godot_cpp/classes/input_event_mouse.hpp>
|
|
#include <godot_cpp/classes/input_event_mouse_button.hpp>
|
|
#include <godot_cpp/classes/sub_viewport.hpp>
|
|
#include <godot_cpp/classes/texture_rect.hpp>
|
|
#include <godot_cpp/classes/timer.hpp>
|
|
#include <godot_cpp/variant/packed_byte_array.hpp>
|
|
#include <libtsm.h>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
using namespace godot;
|
|
|
|
class Terminal : public Control {
|
|
GDCLASS(Terminal, Control)
|
|
|
|
public:
|
|
Terminal();
|
|
~Terminal();
|
|
|
|
enum UpdateMode {
|
|
DISABLED,
|
|
AUTO,
|
|
ALL,
|
|
ALL_NEXT_FRAME,
|
|
};
|
|
|
|
static const UpdateMode UPDATE_MODE_DISABLED = UpdateMode::DISABLED;
|
|
static const UpdateMode UPDATE_MODE_AUTO = UpdateMode::AUTO;
|
|
static const UpdateMode UPDATE_MODE_ALL = UpdateMode::ALL;
|
|
static const UpdateMode UPDATE_MODE_ALL_NEXT_FRAME =
|
|
UpdateMode::ALL_NEXT_FRAME;
|
|
|
|
bool copy_on_selection = false;
|
|
void set_copy_on_selection(bool value);
|
|
bool get_copy_on_selection();
|
|
|
|
UpdateMode update_mode = UPDATE_MODE_AUTO;
|
|
void set_update_mode(UpdateMode value);
|
|
UpdateMode get_update_mode();
|
|
|
|
double bell_cooldown = 0.1f;
|
|
void set_bell_cooldown(double value);
|
|
double get_bell_cooldown();
|
|
|
|
bool bell_muted = false;
|
|
void set_bell_muted(bool value);
|
|
bool get_bell_muted();
|
|
|
|
bool blink_enabled = true;
|
|
void set_blink_enabled(bool value);
|
|
bool get_blink_enabled();
|
|
|
|
double blink_time_off = 0.3;
|
|
void set_blink_time_off(double value);
|
|
double get_blink_time_off();
|
|
|
|
double blink_time_on = 0.6;
|
|
void set_blink_time_on(double value);
|
|
double get_blink_time_on();
|
|
|
|
void clear();
|
|
String copy_all();
|
|
String copy_selection();
|
|
int get_cols();
|
|
int get_rows();
|
|
void write(Variant data);
|
|
|
|
void _gui_input(Ref<InputEvent> event);
|
|
void _notification(int what);
|
|
|
|
void _flush();
|
|
void _on_back_buffer_draw();
|
|
void _on_selection_held();
|
|
void _toggle_blink();
|
|
|
|
protected:
|
|
static void _bind_methods();
|
|
|
|
private:
|
|
struct ColorDef {
|
|
const char *default_color;
|
|
tsm_vte_color tsm_color;
|
|
};
|
|
|
|
struct ThemeCache {
|
|
int font_size = 0;
|
|
std::map<String, Ref<Font>> fonts = std::map<String, Ref<Font>>{};
|
|
std::map<String, Color> colors = std::map<String, Color>{};
|
|
} theme_cache;
|
|
|
|
typedef std::map<const char *, ColorDef> ColorMap;
|
|
typedef std::pair<Color, Color> ColorPair;
|
|
typedef std::map<const char *, const char *> FontMap;
|
|
typedef std::map<std::pair<Key, char32_t>, uint32_t> KeyMap;
|
|
|
|
static const KeyMap KEY_MAP;
|
|
static const ColorMap COLORS;
|
|
static const FontMap FONTS;
|
|
|
|
enum SelectionMode { NONE, POINTER };
|
|
|
|
Control *back_buffer = new Control();
|
|
SubViewport *sub_viewport = new SubViewport();
|
|
TextureRect *front_buffer = new TextureRect();
|
|
|
|
Timer *bell_timer = new Timer();
|
|
Timer *blink_timer = new Timer();
|
|
Timer *selection_timer = new Timer();
|
|
|
|
tsm_screen *screen;
|
|
tsm_vte *vte;
|
|
|
|
Array write_buffer = Array();
|
|
|
|
int cols = 80;
|
|
int rows = 24;
|
|
|
|
// Whether blinking characters are visible. Not whether blinking is enabled
|
|
// which is determined by `blink_enabled`.
|
|
bool blink_on = true;
|
|
|
|
Vector2 cell_size = Vector2(0, 0);
|
|
|
|
std::map<int, Color> palette = {};
|
|
|
|
tsm_age_t framebuffer_age;
|
|
|
|
Ref<InputEventKey> last_input_event_key;
|
|
|
|
bool selecting = false;
|
|
SelectionMode selection_mode = SelectionMode::NONE;
|
|
|
|
static void _bell_cb(tsm_vte *vte, void *data);
|
|
static int _text_draw_cb(tsm_screen *con, uint64_t id, const uint32_t *ch,
|
|
size_t len, unsigned int width, unsigned int col,
|
|
unsigned int row, const tsm_screen_attr *attr,
|
|
tsm_age_t age, void *data);
|
|
static void _write_cb(tsm_vte *vte, const char *u8, size_t len, void *data);
|
|
|
|
void _draw_background(int row, int col, Color bgcol, int width);
|
|
void _draw_foreground(int row, int col, char *ch, const tsm_screen_attr *attr,
|
|
Color fgcol);
|
|
ColorPair _get_cell_colors(const tsm_screen_attr *attr);
|
|
void _handle_key_input(Ref<InputEventKey> event);
|
|
void _handle_mouse_wheel(Ref<InputEventMouseButton> event);
|
|
void _handle_selection(Ref<InputEventMouse> event);
|
|
void _recalculate_size();
|
|
void _refresh();
|
|
void _update_theme_item_cache();
|
|
};
|
|
|
|
VARIANT_ENUM_CAST(Terminal::UpdateMode);
|
|
|
|
#endif // GODOT_XTERM_TERMINAL_H
|