Compare commits
6 Commits
bf01b935bd
...
7f25ddc229
Author | SHA1 | Date |
---|---|---|
Bananymous | 7f25ddc229 | |
Bananymous | 163961df4f | |
Bananymous | 97da386ed6 | |
Bananymous | c706829a91 | |
Bananymous | 6cd246a38e | |
Bananymous | 43e88c0ae0 |
Binary file not shown.
|
@ -168,7 +168,7 @@ index 0000000..9161771
|
|||
+{
|
||||
+ for (size_t y = 0; y < DOOMGENERIC_RESY; y++)
|
||||
+ for (size_t x = 0; x < DOOMGENERIC_RESX; x++)
|
||||
+ s_window->set_pixel(x, y, DG_ScreenBuffer[y * DOOMGENERIC_RESX + x]);
|
||||
+ s_window->set_pixel(x, y, 0xFF000000 | DG_ScreenBuffer[y * DOOMGENERIC_RESX + x]);
|
||||
+ s_window->invalidate();
|
||||
+ s_window->poll_events();
|
||||
+}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace LibGUI
|
|||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
BAN::Vector<uint32_t> framebuffer;
|
||||
TRY(framebuffer.resize(width * height));
|
||||
TRY(framebuffer.resize(width * height, 0xFF000000));
|
||||
|
||||
int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if (server_fd == -1)
|
||||
|
|
|
@ -9,6 +9,28 @@
|
|||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static constexpr uint32_t s_colors_dark[] {
|
||||
0xCC'000000,
|
||||
0xCC'FF0000,
|
||||
0xCC'00FF00,
|
||||
0xCC'FFFF00,
|
||||
0xCC'0000FF,
|
||||
0xCC'FF00FF,
|
||||
0xCC'00FFFF,
|
||||
0xCC'BFBFBF,
|
||||
};
|
||||
|
||||
static constexpr uint32_t s_colors_bright[] {
|
||||
0xCC'3F3F3F,
|
||||
0xCC'FF7F7F,
|
||||
0xCC'7FFF7F,
|
||||
0xCC'FFFF7F,
|
||||
0xCC'7F7FFF,
|
||||
0xCC'FF7FFF,
|
||||
0xCC'7FFFFF,
|
||||
0xCC'FFFFFF,
|
||||
};
|
||||
|
||||
void Terminal::start_shell()
|
||||
{
|
||||
int pts_master = posix_openpt(O_RDWR | O_NOCTTY);
|
||||
|
@ -85,6 +107,9 @@ void Terminal::run()
|
|||
signal(SIGCHLD, [](int) { s_shell_exited = true; });
|
||||
start_shell();
|
||||
|
||||
m_bg_color = s_colors_dark[0];
|
||||
m_fg_color = s_colors_bright[7];
|
||||
|
||||
m_window = MUST(LibGUI::Window::create(600, 400, "Terminal"_sv));
|
||||
m_window->fill(m_bg_color);
|
||||
m_window->invalidate();
|
||||
|
@ -184,45 +209,23 @@ bool Terminal::read_shell()
|
|||
|
||||
void Terminal::handle_sgr()
|
||||
{
|
||||
constexpr uint32_t colors_dark[] {
|
||||
0xFF'000000,
|
||||
0xFF'FF0000,
|
||||
0xFF'00FF00,
|
||||
0xFF'FFFF00,
|
||||
0xFF'0000FF,
|
||||
0xFF'FF00FF,
|
||||
0xFF'00FFFF,
|
||||
0xFF'BFBFBF,
|
||||
};
|
||||
|
||||
constexpr uint32_t colors_bright[] {
|
||||
0xFF'3F3F3F,
|
||||
0xFF'FF7F7F,
|
||||
0xFF'7FFF7F,
|
||||
0xFF'FFFF7F,
|
||||
0xFF'7F7FFF,
|
||||
0xFF'FF7FFF,
|
||||
0xFF'7FFFFF,
|
||||
0xFF'FFFFFF,
|
||||
};
|
||||
|
||||
switch (m_csi_info.fields[0])
|
||||
{
|
||||
case -1: case 0:
|
||||
m_fg_color = 0xFFFFFF;
|
||||
m_bg_color = 0x000000;
|
||||
m_bg_color = s_colors_dark[0];
|
||||
m_fg_color = s_colors_bright[7];
|
||||
break;
|
||||
case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
|
||||
m_fg_color = colors_dark[m_csi_info.fields[0] - 30];
|
||||
m_fg_color = s_colors_dark[m_csi_info.fields[0] - 30];
|
||||
break;
|
||||
case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
|
||||
m_bg_color = colors_dark[m_csi_info.fields[0] - 40];
|
||||
m_bg_color = s_colors_dark[m_csi_info.fields[0] - 40];
|
||||
break;
|
||||
case 90: case 91: case 92: case 93: case 94: case 95: case 96: case 97:
|
||||
m_fg_color = colors_bright[m_csi_info.fields[0] - 90];
|
||||
m_fg_color = s_colors_bright[m_csi_info.fields[0] - 90];
|
||||
break;
|
||||
case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107:
|
||||
m_bg_color = colors_bright[m_csi_info.fields[0] - 100];
|
||||
m_bg_color = s_colors_bright[m_csi_info.fields[0] - 100];
|
||||
break;
|
||||
default:
|
||||
dprintln("TODO: SGR {}", m_csi_info.fields[0]);
|
||||
|
|
|
@ -70,6 +70,6 @@ private:
|
|||
uint8_t m_utf8_bytes[4] { };
|
||||
|
||||
Cursor m_saved_cursor { 0, 0 };
|
||||
uint32_t m_fg_color { 0xFFFFFF };
|
||||
uint32_t m_bg_color { 0x000000 };
|
||||
uint32_t m_fg_color { 0 };
|
||||
uint32_t m_bg_color { 0 };
|
||||
};
|
||||
|
|
|
@ -39,7 +39,7 @@ void Window::prepare_title_bar(const LibFont::Font& font)
|
|||
uint32_t* title_bar_data = new uint32_t[title_bar_bytes];
|
||||
ASSERT(title_bar_data);
|
||||
for (size_t i = 0; i < title_bar_bytes; i++)
|
||||
title_bar_data[i] = 0xFFFFFF;
|
||||
title_bar_data[i] = 0xFFFFFFFF;
|
||||
|
||||
const auto text_area = title_text_area();
|
||||
|
||||
|
@ -61,7 +61,7 @@ void Window::prepare_title_bar(const LibFont::Font& font)
|
|||
break;
|
||||
const uint8_t bitmask = 1 << (font.width() - x - 1);
|
||||
if (glyph[y * font.pitch()] & bitmask)
|
||||
title_bar_data[(y_off + y) * title_bar_width() + (x_off + x)] = 0x000000;
|
||||
title_bar_data[(y_off + y) * title_bar_width() + (x_off + x)] = 0xFF000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
ASSERT(title_bar_area().contains({ abs_x, abs_y }));
|
||||
|
||||
if (auto close_button = close_button_area(); close_button.contains({ abs_x, abs_y }))
|
||||
return close_button.contains(cursor) ? 0xFF0000 : 0xD00000;
|
||||
return close_button.contains(cursor) ? 0xFFFF0000 : 0xFFD00000;
|
||||
|
||||
int32_t rel_x = abs_x - title_bar_x();
|
||||
int32_t rel_y = abs_y - title_bar_y();
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
WindowServer::WindowServer(Framebuffer& framebuffer)
|
||||
WindowServer::WindowServer(Framebuffer& framebuffer, int32_t corner_radius)
|
||||
: m_framebuffer(framebuffer)
|
||||
, m_corner_radius(corner_radius)
|
||||
, m_cursor({ framebuffer.width / 2, framebuffer.height / 2 })
|
||||
, m_font(MUST(LibFont::Font::load("/usr/share/fonts/lat0-16.psfu"_sv)))
|
||||
{
|
||||
|
@ -166,6 +167,10 @@ void WindowServer::on_key_event(LibInput::KeyEvent event)
|
|||
return;
|
||||
}
|
||||
|
||||
// Toggle window bounce with F2
|
||||
if (event.pressed() && event.key == LibInput::Key::F2)
|
||||
m_is_bouncing_window = !m_is_bouncing_window;
|
||||
|
||||
if (m_focused_window)
|
||||
{
|
||||
LibGUI::EventPacket packet;
|
||||
|
@ -297,6 +302,21 @@ void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t alpha_blend(uint32_t color_a, uint32_t color_b)
|
||||
{
|
||||
const uint32_t a_a = color_a >> 24;
|
||||
const uint32_t a_b = ((color_b >> 24) * (256 - a_a)) >> 8;
|
||||
const uint32_t a = a_a + a_b;
|
||||
|
||||
const uint32_t rb1 = (a_a * (color_a & 0xFF00FF)) >> 8;
|
||||
const uint32_t rb2 = (a_b * (color_b & 0xFF00FF)) >> 8;
|
||||
|
||||
const uint32_t g1 = (a_a * (color_a & 0x00FF00)) >> 8;
|
||||
const uint32_t g2 = (a_b * (color_b & 0x00FF00)) >> 8;
|
||||
|
||||
return (a << 24) | ((rb1 | rb2) & 0xFF00FF) | ((g1 | g2) & 0x00FF00);
|
||||
}
|
||||
|
||||
void WindowServer::invalidate(Rectangle area)
|
||||
{
|
||||
auto fb_overlap = area.get_overlap(m_framebuffer.area());
|
||||
|
@ -315,42 +335,170 @@ void WindowServer::invalidate(Rectangle area)
|
|||
else
|
||||
{
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
memset(&m_framebuffer.mmap[y * m_framebuffer.width + area.x], 0x10, area.width * 4);
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = 0xFF101010;
|
||||
}
|
||||
|
||||
for (auto& pwindow : m_client_windows)
|
||||
{
|
||||
auto& window = *pwindow;
|
||||
|
||||
// window title bar
|
||||
if (auto overlap = window.title_bar_area().get_overlap(area); overlap.has_value())
|
||||
{
|
||||
for (int32_t y_off = 0; y_off < overlap->height; y_off++)
|
||||
const Rectangle fast_areas[] {
|
||||
{
|
||||
for (int32_t x_off = 0; x_off < overlap->width; x_off++)
|
||||
window.full_x() + m_corner_radius,
|
||||
window.full_y(),
|
||||
window.full_width() - 2 * m_corner_radius,
|
||||
m_corner_radius
|
||||
},
|
||||
{
|
||||
window.full_x(),
|
||||
window.full_y() + m_corner_radius,
|
||||
window.full_width(),
|
||||
window.full_height() - 2 * m_corner_radius
|
||||
},
|
||||
{
|
||||
window.full_x() + m_corner_radius,
|
||||
window.full_y() + window.full_height() - m_corner_radius,
|
||||
window.full_width() - 2 * m_corner_radius,
|
||||
m_corner_radius
|
||||
}
|
||||
};
|
||||
|
||||
const Position corner_centers[] {
|
||||
{
|
||||
window.full_x() + m_corner_radius,
|
||||
window.full_y() + m_corner_radius,
|
||||
},
|
||||
{
|
||||
window.full_x() + (window.full_width() - 1) - m_corner_radius,
|
||||
window.full_y() + m_corner_radius,
|
||||
},
|
||||
{
|
||||
window.full_x() + m_corner_radius,
|
||||
window.full_y() + (window.full_height() - 1) - m_corner_radius,
|
||||
},
|
||||
{
|
||||
window.full_x() + (window.full_width() - 1) - m_corner_radius,
|
||||
window.full_y() + (window.full_height() - 1) - m_corner_radius,
|
||||
},
|
||||
};
|
||||
|
||||
const Rectangle corner_areas[] {
|
||||
{
|
||||
window.full_x(),
|
||||
window.full_y(),
|
||||
m_corner_radius,
|
||||
m_corner_radius
|
||||
},
|
||||
{
|
||||
window.full_x() + window.full_width() - m_corner_radius,
|
||||
window.full_y(),
|
||||
m_corner_radius,
|
||||
m_corner_radius
|
||||
},
|
||||
{
|
||||
window.full_x(),
|
||||
window.full_y() + window.full_height() - m_corner_radius,
|
||||
m_corner_radius,
|
||||
m_corner_radius
|
||||
},
|
||||
{
|
||||
window.full_x() + window.full_width() - m_corner_radius,
|
||||
window.full_y() + window.full_height() - m_corner_radius,
|
||||
m_corner_radius,
|
||||
m_corner_radius
|
||||
}
|
||||
};
|
||||
|
||||
const auto is_rounded_off =
|
||||
[&](Position pos) -> bool
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
uint32_t pixel = window.title_bar_pixel(
|
||||
overlap->x + x_off,
|
||||
overlap->y + y_off,
|
||||
m_cursor
|
||||
);
|
||||
m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x + x_off] = pixel;
|
||||
if (!corner_areas[i].contains(pos))
|
||||
continue;
|
||||
const int32_t dx = pos.x - corner_centers[i].x;
|
||||
const int32_t dy = pos.y - corner_centers[i].y;
|
||||
if (2 * (dy > 0) + (dx > 0) != i)
|
||||
continue;
|
||||
if (dx * dx + dy * dy >= m_corner_radius * m_corner_radius)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// window title bar
|
||||
if (auto title_overlap = window.title_bar_area().get_overlap(area); title_overlap.has_value())
|
||||
{
|
||||
for (int32_t y_off = 0; y_off < title_overlap->height; y_off++)
|
||||
{
|
||||
for (int32_t x_off = 0; x_off < title_overlap->width; x_off++)
|
||||
{
|
||||
const int32_t abs_x = title_overlap->x + x_off;
|
||||
const int32_t abs_y = title_overlap->y + y_off;
|
||||
if (is_rounded_off({ abs_x, abs_y }))
|
||||
continue;
|
||||
|
||||
const uint32_t color = window.title_bar_pixel(abs_x, abs_y, m_cursor);
|
||||
m_framebuffer.mmap[abs_y * m_framebuffer.width + abs_x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// window client area
|
||||
if (auto overlap = window.client_area().get_overlap(area); overlap.has_value())
|
||||
if (auto client_overlap = window.client_area().get_overlap(area); client_overlap.has_value())
|
||||
{
|
||||
const int32_t src_x = overlap->x - window.client_x();
|
||||
const int32_t src_y = overlap->y - window.client_y();
|
||||
for (int32_t y_off = 0; y_off < overlap->height; y_off++)
|
||||
for (const auto& fast_area : fast_areas)
|
||||
{
|
||||
memcpy(
|
||||
&m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x],
|
||||
&window.framebuffer()[(src_y + y_off) * window.client_width() + src_x],
|
||||
overlap->width * 4
|
||||
);
|
||||
auto fast_overlap = client_overlap->get_overlap(fast_area);
|
||||
if (!fast_overlap.has_value())
|
||||
continue;
|
||||
for (int32_t y_off = 0; y_off < fast_overlap->height; y_off++)
|
||||
{
|
||||
const int32_t abs_row_y = fast_overlap->y + y_off;
|
||||
const int32_t abs_row_x = fast_overlap->x;
|
||||
|
||||
const int32_t src_row_y = abs_row_y - window.client_y();
|
||||
const int32_t src_row_x = abs_row_x - window.client_x();
|
||||
|
||||
auto* window_row = &window.framebuffer()[src_row_y * window.client_width() + src_row_x];
|
||||
auto* frameb_row = &m_framebuffer.mmap[ abs_row_y * m_framebuffer.width + abs_row_x];
|
||||
|
||||
for (int32_t i = 0; i < fast_overlap->width; i++)
|
||||
{
|
||||
const uint32_t color_a = *window_row;
|
||||
const uint32_t color_b = *frameb_row;
|
||||
*frameb_row = alpha_blend(color_a, color_b);
|
||||
|
||||
window_row++;
|
||||
frameb_row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& corner_area : corner_areas)
|
||||
{
|
||||
auto corner_overlap = client_overlap->get_overlap(corner_area);
|
||||
if (!corner_overlap.has_value())
|
||||
continue;
|
||||
for (int32_t y_off = 0; y_off < corner_overlap->height; y_off++)
|
||||
{
|
||||
for (int32_t x_off = 0; x_off < corner_overlap->width; x_off++)
|
||||
{
|
||||
const int32_t abs_x = corner_overlap->x + x_off;
|
||||
const int32_t abs_y = corner_overlap->y + y_off;
|
||||
if (is_rounded_off({ abs_x, abs_y }))
|
||||
continue;
|
||||
|
||||
const int32_t src_x = abs_x - window.client_x();
|
||||
const int32_t src_y = abs_y - window.client_y();
|
||||
|
||||
const uint32_t color_a = window.framebuffer()[src_y * window.client_width() + src_x];
|
||||
const uint32_t color_b = m_framebuffer.mmap[abs_y * m_framebuffer.width + abs_x];
|
||||
|
||||
m_framebuffer.mmap[abs_y * m_framebuffer.width + abs_x] = alpha_blend(color_a, color_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -391,6 +539,25 @@ void WindowServer::invalidate(Rectangle area)
|
|||
|
||||
void WindowServer::sync()
|
||||
{
|
||||
if (m_focused_window && m_is_bouncing_window)
|
||||
{
|
||||
static int32_t dir_x = 7;
|
||||
static int32_t dir_y = 4;
|
||||
auto old_window = m_focused_window->full_area();
|
||||
m_focused_window->set_position({
|
||||
m_focused_window->client_x() + dir_x,
|
||||
m_focused_window->client_y() + dir_y,
|
||||
});
|
||||
auto new_window = m_focused_window->full_area();
|
||||
invalidate(old_window);
|
||||
invalidate(new_window);
|
||||
|
||||
if ((m_focused_window->full_x() < 0 && dir_x < 0) || (m_focused_window->full_x() + m_focused_window->full_width() >= m_framebuffer.width && dir_x > 0))
|
||||
dir_x = -dir_x;
|
||||
if ((m_focused_window->full_y() < 0 && dir_y < 0) || (m_focused_window->full_y() + m_focused_window->full_height() >= m_framebuffer.height && dir_y > 0))
|
||||
dir_y = -dir_y;
|
||||
}
|
||||
|
||||
size_t synced_pages = 0;
|
||||
|
||||
for (size_t i = 0; i < m_pages_to_sync_bitmap.size() * 8; i++)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
class WindowServer
|
||||
{
|
||||
public:
|
||||
WindowServer(Framebuffer& framebuffer);
|
||||
WindowServer(Framebuffer& framebuffer, int32_t corner_radius);
|
||||
|
||||
BAN::ErrorOr<void> set_background_image(BAN::UniqPtr<LibImage::Image>);
|
||||
|
||||
|
@ -48,6 +48,8 @@ private:
|
|||
BAN::Vector<BAN::RefPtr<Window>> m_client_windows;
|
||||
BAN::Vector<int> m_client_fds;
|
||||
|
||||
const int32_t m_corner_radius;
|
||||
|
||||
BAN::Vector<uint8_t> m_pages_to_sync_bitmap;
|
||||
|
||||
BAN::UniqPtr<LibImage::Image> m_background_image;
|
||||
|
@ -59,6 +61,7 @@ private:
|
|||
|
||||
bool m_deleted_window { false };
|
||||
bool m_is_stopped { false };
|
||||
bool m_is_bouncing_window = false;
|
||||
|
||||
LibFont::Font m_font;
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
struct Config
|
||||
{
|
||||
BAN::UniqPtr<LibImage::Image> background_image;
|
||||
int32_t corner_radius = 0;
|
||||
};
|
||||
|
||||
BAN::Optional<BAN::String> file_read_line(FILE* file)
|
||||
|
@ -88,6 +89,15 @@ Config parse_config()
|
|||
else
|
||||
config.background_image = image.release_value();
|
||||
}
|
||||
else if (variable == "corner-radius"_sv)
|
||||
{
|
||||
char* endptr = nullptr;
|
||||
long corner_radius = strtol(value.data(), &endptr, 0);
|
||||
if (corner_radius < 0 || corner_radius == LONG_MAX || corner_radius >= INT32_MAX)
|
||||
dwarnln("invalid corner-radius: '{}'", value);
|
||||
else
|
||||
config.corner_radius = corner_radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwarnln("Unknown config variable: {}", variable);
|
||||
|
@ -176,7 +186,7 @@ int main()
|
|||
|
||||
auto config = parse_config();
|
||||
|
||||
WindowServer window_server(framebuffer);
|
||||
WindowServer window_server(framebuffer, config.corner_radius);
|
||||
if (config.background_image)
|
||||
if (auto ret = window_server.set_background_image(BAN::move(config.background_image)); ret.is_error())
|
||||
dwarnln("Could not set background image: {}", ret.error());
|
||||
|
|
|
@ -10,7 +10,7 @@ void randomize_color(BAN::UniqPtr<LibGUI::Window>& window)
|
|||
uint32_t color = ((rand() % 255) << 16) | ((rand() % 255) << 8) | ((rand() % 255) << 0);
|
||||
for (uint32_t y = 0; y < window->height(); y++)
|
||||
for (uint32_t x = 0; x < window->width(); x++)
|
||||
window->set_pixel(x, y, color);
|
||||
window->set_pixel(x, y, 0xFF000000 | color);
|
||||
window->invalidate();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue