Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/kernel/editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <kernel/keyboard.h>
#include <kernel/vfs.h>
#include <kernel/process.h>

#define EDITOR_MAX_LINES 128
#define EDITOR_LINE_LENGTH 128
Expand All @@ -25,6 +26,9 @@ class Editor {
void exit(bool save);
void render();
void draw_line(const char* text, int y, bool active_line);
void put_cell(size_t x, size_t y, char ch, uint8_t color);
void present_window();
void update_cursor_visual(size_t row, size_t column, bool active);

void handle_char(char c);
void handle_enter();
Expand All @@ -48,6 +52,7 @@ class Editor {
bool active;

char status_message[EDITOR_LINE_LENGTH]; // status bar message
Process* owner_proc = nullptr;
};

void editor_start(const char* path);
Expand Down
32 changes: 32 additions & 0 deletions include/kernel/graphics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <stddef.h>
#include <stdint.h>

#include <kernel/vga.h>

namespace graphics
{
using Color = uint8_t;

// Construct a VGA color value compatible with text-mode windows.
Color make_color(vga_color foreground, vga_color background);

size_t columns();
size_t rows();

// Ensure the current process owns a window before drawing.
void ensure_window();

void clear(Color color, char fill_char = ' ');

void put_char(size_t column, size_t row, char ch, Color color);
void draw_text(size_t column, size_t row, const char *text, Color color);
void fill_rect(size_t column, size_t row, size_t width, size_t height, char ch, Color color);

void set_cursor(size_t row, size_t column, bool active);
bool get_cursor(size_t &row, size_t &column);

void present();
} // namespace graphics

6 changes: 6 additions & 0 deletions include/kernel/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdint.h>
#include <sys/gui.h>
#include <kernel/mouse.h>

class Terminal;
struct Process;
Expand All @@ -16,4 +17,9 @@ uint32_t background_color_for_row(uint32_t y);
void fill_background_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
void set_background_fill_override(uint32_t color);
void clear_background_fill_override();

void initialize_mouse_cursor(int32_t x, int32_t y, uint8_t buttons);
void handle_mouse_event(const MouseEvent &event, Terminal &terminal);
void begin_window_redraw();
void end_window_redraw();
}
2 changes: 1 addition & 1 deletion include/kernel/hooks.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#pragma once
#include <stdint.h>

enum class HookType {
Expand Down
36 changes: 36 additions & 0 deletions include/kernel/mouse.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
#pragma once

#include <stdint.h>

#define MOUSE_BUTTON_LEFT 0x01u
#define MOUSE_BUTTON_RIGHT 0x02u
#define MOUSE_BUTTON_MIDDLE 0x04u

typedef struct MouseEvent
{
int32_t x;
int32_t y;
int16_t dx;
int16_t dy;
int8_t scroll_x;
int8_t scroll_y;
uint8_t buttons;
uint8_t changed;
int32_t target_pid;
} MouseEvent;

typedef struct MouseState
{
int32_t x;
int32_t y;
uint8_t buttons;
uint8_t available;
} MouseState;

#ifdef __cplusplus
extern "C" {
#endif

void mouse_initialize();
MouseState mouse_get_state();

#ifdef __cplusplus
}
#endif
6 changes: 6 additions & 0 deletions include/kernel/terminal_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdint.h>
#include <stddef.h>
#include <kernel/mouse.h>

class Terminal;
struct Process;
Expand All @@ -15,4 +16,9 @@ void activate_process(Process *proc, Terminal &terminal);
void set_active_window_origin(Terminal &terminal, Process *proc, int32_t x, int32_t y);
void on_process_exit(Process *proc, Terminal &terminal);
void write_text(Terminal &terminal, Process *proc, const char *text, size_t length);
bool handle_mouse_event(Terminal &terminal, const MouseEvent &event);
void window_put_char(Process *proc, size_t x, size_t y, char ch, uint8_t color);
void window_set_cursor(Process *proc, size_t row, size_t column, bool active);
void window_present(Process *proc);
bool window_get_cursor(Process *proc, size_t &row, size_t &column);
}
3 changes: 3 additions & 0 deletions libc/include/sys/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <stdint.h>
#include <kernel/keyboard.h>
#include <kernel/mouse.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -11,6 +12,7 @@ extern "C" {
typedef enum {
EVENT_NONE = 0,
EVENT_KEYBOARD,
EVENT_MOUSE,
EVENT_PROCESS,
EVENT_PCI,
} EventType;
Expand All @@ -35,6 +37,7 @@ typedef struct {
EventType type;
union {
keyboard_event keyboard;
MouseEvent mouse;
process_event_data process;
pci_event_data pci;
} data;
Expand Down
210 changes: 210 additions & 0 deletions src/kernel/graphics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#include <kernel/graphics.h>

#include <kernel/framebuffer.h>
#include <kernel/terminal_windows.h>
#include <kernel/scheduler.h>
#include <kernel/process.h>

extern Terminal terminal;

namespace graphics
{
namespace
{
Process *current_process()
{
return scheduler_current_process();
}

bool ensure_window_for(Process *proc)
{
if (proc == nullptr || !framebuffer::is_available())
{
return false;
}

size_t dummy_row = 0;
size_t dummy_col = 0;
if (!terminal_windows::window_get_cursor(proc, dummy_row, dummy_col))
{
terminal_windows::request_new_window(terminal, proc);
}

return terminal_windows::window_get_cursor(proc, dummy_row, dummy_col);
}
} // namespace

Color make_color(vga_color foreground, vga_color background)
{
return terminal.make_color(foreground, background);
}

size_t columns()
{
return Terminal::VGA_WIDTH;
}

size_t rows()
{
return Terminal::VGA_HEIGHT;
}

void ensure_window()
{
(void)ensure_window_for(current_process());
}

void clear(Color color, char fill_char)
{
Process *proc = current_process();
if (!ensure_window_for(proc))
{
return;
}

const size_t max_columns = columns();
const size_t max_rows = rows();

for (size_t row = 0; row < max_rows; ++row)
{
for (size_t col = 0; col < max_columns; ++col)
{
terminal_windows::window_put_char(proc, col, row, fill_char, color);
}
}

terminal_windows::window_set_cursor(proc, 0, 0, false);
}

void put_char(size_t column, size_t row, char ch, Color color)
{
Process *proc = current_process();
if (!ensure_window_for(proc))
{
return;
}

if (column >= columns() || row >= rows())
{
return;
}

terminal_windows::window_put_char(proc, column, row, ch, color);
}

void draw_text(size_t column, size_t row, const char *text, Color color)
{
if (text == nullptr)
{
return;
}

Process *proc = current_process();
if (!ensure_window_for(proc))
{
return;
}

size_t cursor_col = column;
size_t cursor_row = row;
const size_t max_columns = columns();
const size_t max_rows = rows();

for (size_t i = 0; text[i] != '\0'; ++i)
{
char ch = text[i];

if (ch == '\n')
{
cursor_col = column;
if (++cursor_row >= max_rows)
{
break;
}
continue;
}

if (cursor_col >= max_columns)
{
cursor_col = column;
if (++cursor_row >= max_rows)
{
break;
}
}

terminal_windows::window_put_char(proc, cursor_col, cursor_row, ch, color);
++cursor_col;
}
}

void fill_rect(size_t column, size_t row, size_t width, size_t height, char ch, Color color)
{
Process *proc = current_process();
if (!ensure_window_for(proc))
{
return;
}

const size_t max_columns = columns();
const size_t max_rows = rows();

for (size_t y = 0; y < height; ++y)
{
size_t target_row = row + y;
if (target_row >= max_rows)
{
break;
}

for (size_t x = 0; x < width; ++x)
{
size_t target_col = column + x;
if (target_col >= max_columns)
{
break;
}

terminal_windows::window_put_char(proc, target_col, target_row, ch, color);
}
}
}

void set_cursor(size_t row, size_t column, bool active)
{
Process *proc = current_process();
if (!ensure_window_for(proc))
{
return;
}

terminal_windows::window_set_cursor(proc, row, column, active);
}

bool get_cursor(size_t &row, size_t &column)
{
row = 0;
column = 0;

Process *proc = current_process();
if (!ensure_window_for(proc))
{
return false;
}

return terminal_windows::window_get_cursor(proc, row, column);
}

void present()
{
Process *proc = current_process();
if (!ensure_window_for(proc))
{
return;
}

terminal_windows::window_present(proc);
}

} // namespace graphics

Loading