New Feature(s):
-Network UI
-Pattern Wallpapers
This commit is contained in:
Chris 2026-02-05 22:38:21 +01:00
parent 89bdb860dd
commit a90f41d8a3
13 changed files with 600 additions and 60 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,4 @@
# Brew OS 1.03 Pre-Alpha # Brew OS 1.10 Alpha
## Brewkernel is now BrewOS! ## Brewkernel is now BrewOS!
Brewkernel will from now on be deprecated as it's core became too messy. I have built a less bloated kernel and wrote a DE above it, which is why it is now an OS instead of a kernel (in my opinion). Brewkernel will from now on be deprecated as it's core became too messy. I have built a less bloated kernel and wrote a DE above it, which is why it is now an OS instead of a kernel (in my opinion).
@ -9,6 +9,7 @@ Brew Kernel is a simple x86_64 hobbyist operating system.
It features a DE (and WM), a FAT32 filesystem, customizable UI and much much more! It features a DE (and WM), a FAT32 filesystem, customizable UI and much much more!
## Features ## Features
- Basic Networking Stack
- Brew WM - Brew WM
- Fat 32 FS - Fat 32 FS
- 64-bit long mode support - 64-bit long mode support

Binary file not shown.

View file

@ -2,6 +2,7 @@
#include "graphics.h" #include "graphics.h"
#include <stddef.h> #include <stddef.h>
#include "wm.h" #include "wm.h"
#include "network.h"
Window win_control_panel; Window win_control_panel;
@ -15,14 +16,101 @@ Window win_control_panel;
// Control panel state // Control panel state
#define VIEW_MAIN 0 #define VIEW_MAIN 0
#define VIEW_WALLPAPER 1 #define VIEW_WALLPAPER 1
#define VIEW_NETWORK 2
static int current_view = VIEW_MAIN; static int current_view = VIEW_MAIN;
static char rgb_r[4] = ""; static char rgb_r[4] = "";
static char rgb_g[4] = ""; static char rgb_g[4] = "";
static char rgb_b[4] = ""; static char rgb_b[4] = "";
static int focused_field = -1; // -1=none, 0=R, 1=G, 2=B static int focused_field = -1;
static int input_cursor = 0; static int input_cursor = 0;
// Network panel state
static char ip_1[4] = "";
static char ip_2[4] = "";
static char ip_3[4] = "";
static char ip_4[4] = "";
static char dest_ip_1[4] = "";
static char dest_ip_2[4] = "";
static char dest_ip_3[4] = "";
static char dest_ip_4[4] = "";
static char udp_port[6] = "";
static char udp_message[128] = "";
static char net_status[64] = "";
// Pattern buffers (128x128)
#define PATTERN_SIZE 128
static uint32_t pattern_lumberjack[PATTERN_SIZE * PATTERN_SIZE];
static uint32_t pattern_blue_diamond[PATTERN_SIZE * PATTERN_SIZE];
static void generate_lumberjack_pattern(void) {
// Lumberjack pattern: 3x3 repeating cell
// Red corners, dark grey cross (top/left/right/bottom), black center
uint32_t red = 0xFFDC143C;
uint32_t dark_grey = 0xFF404040;
uint32_t black = 0xFF000000;
// Fill entire pattern with the 3x3 repeating cell
for (int y = 0; y < PATTERN_SIZE; y++) {
for (int x = 0; x < PATTERN_SIZE; x++) {
int cell_x = x % 3;
int cell_y = y % 3;
uint32_t color;
// Determine color based on position in 3x3 cell
if (cell_x == 1 && cell_y == 1) {
// Center: black
color = black;
} else if (cell_x == 1 || cell_y == 1) {
// Cross (top, left, right, bottom): dark grey
color = dark_grey;
} else {
// Corners: red
color = red;
}
pattern_lumberjack[y * PATTERN_SIZE + x] = color;
}
}
}
static void generate_blue_diamond_pattern(void) {
// Blue diamond pattern on light blue background
uint32_t bg_color = 0xFFADD8E6; // Light blue
uint32_t diamond_color = 0xFF0000CD; // Medium blue
for (int y = 0; y < PATTERN_SIZE; y++) {
for (int x = 0; x < PATTERN_SIZE; x++) {
pattern_blue_diamond[y * PATTERN_SIZE + x] = bg_color;
}
}
// Draw diamonds (centered at 32, 32 and 96, 96)
for (int dy = -24; dy <= 24; dy++) {
for (int dx = -24; dx <= 24; dx++) {
// Diamond shape: |dx| + |dy| <= 24
int abs_dx = dx < 0 ? -dx : dx;
int abs_dy = dy < 0 ? -dy : dy;
if (abs_dx + abs_dy <= 24) {
// Top-left diamond
int x1 = 32 + dx;
int y1 = 32 + dy;
if (x1 >= 0 && x1 < PATTERN_SIZE && y1 >= 0 && y1 < PATTERN_SIZE) {
pattern_blue_diamond[y1 * PATTERN_SIZE + x1] = diamond_color;
}
// Bottom-right diamond
int x2 = 96 + dx;
int y2 = 96 + dy;
if (x2 >= 0 && x2 < PATTERN_SIZE && y2 >= 0 && y2 < PATTERN_SIZE) {
pattern_blue_diamond[y2 * PATTERN_SIZE + x2] = diamond_color;
}
}
}
}
}
static uint32_t parse_rgb_separate(const char *r, const char *g, const char *b) { static uint32_t parse_rgb_separate(const char *r, const char *g, const char *b) {
int rv = 0, gv = 0, bv = 0; int rv = 0, gv = 0, bv = 0;
@ -59,21 +147,55 @@ static void control_panel_paint_main(Window *win) {
int offset_x = win->x + 8; int offset_x = win->x + 8;
int offset_y = win->y + 30; int offset_y = win->y + 30;
// Draw wallpaper folder icon // Draw wallpaper painting icon
// Folder icon // Frame
draw_rect(offset_x + 5, offset_y, 15, 6, COLOR_LTGRAY); draw_rect(offset_x + 5, offset_y + 2, 28, 20, 0xFF8B4513); // Brown frame
draw_rect(offset_x + 5, offset_y, 15, 1, COLOR_BLACK); draw_rect(offset_x + 6, offset_y + 3, 26, 18, 0xFFFFFFFF); // White canvas
draw_rect(offset_x + 5, offset_y, 1, 6, COLOR_BLACK);
draw_rect(offset_x + 19, offset_y, 1, 6, COLOR_BLACK);
draw_rect(offset_x + 5, offset_y + 6, 25, 15, COLOR_LTGRAY); // Paint strokes (simple landscape)
draw_rect(offset_x + 5, offset_y + 6, 25, 1, COLOR_BLACK); draw_rect(offset_x + 8, offset_y + 5, 22, 7, 0xFF87CEEB); // Sky blue
draw_rect(offset_x + 5, offset_y + 6, 1, 15, COLOR_BLACK); draw_rect(offset_x + 8, offset_y + 12, 22, 5, 0xFF90EE90); // Light green grass
draw_rect(offset_x + 29, offset_y + 6, 1, 15, COLOR_BLACK); draw_rect(offset_x + 15, offset_y + 8, 3, 4, 0xFF8B4513); // Tree trunk
draw_rect(offset_x + 5, offset_y + 20, 25, 1, COLOR_BLACK); draw_rect(offset_x + 13, offset_y + 5, 7, 4, 0xFF228B22); // Tree leaves
draw_rect(offset_x + 24, offset_y + 6, 4, 3, 0xFFFFFF00); // Sun
// Label
draw_string(offset_x + 40, offset_y + 8, "Wallpaper", 0xFF000000); draw_string(offset_x + 40, offset_y + 8, "Wallpaper", 0xFF000000);
// Draw network globe icon
int net_offset_y = offset_y + 35;
// Globe circle (approximate with rectangles for filled circle)
uint32_t globe_color = 0xFF4169E1; // Royal blue
// Draw filled circle using rectangles (simplified)
draw_rect(offset_x + 11, net_offset_y + 3, 12, 1, globe_color);
draw_rect(offset_x + 9, net_offset_y + 4, 16, 1, globe_color);
draw_rect(offset_x + 8, net_offset_y + 5, 18, 1, globe_color);
draw_rect(offset_x + 7, net_offset_y + 6, 20, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 7, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 8, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 9, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 10, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 11, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 12, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 13, 22, 1, globe_color);
draw_rect(offset_x + 7, net_offset_y + 14, 20, 1, globe_color);
draw_rect(offset_x + 8, net_offset_y + 15, 18, 1, globe_color);
draw_rect(offset_x + 9, net_offset_y + 16, 16, 1, globe_color);
draw_rect(offset_x + 11, net_offset_y + 17, 12, 1, globe_color);
// Latitude lines (white)
draw_rect(offset_x + 7, net_offset_y + 8, 20, 1, 0xFFFFFFFF);
draw_rect(offset_x + 7, net_offset_y + 12, 20, 1, 0xFFFFFFFF);
// Longitude line (vertical, white)
draw_rect(offset_x + 17, net_offset_y + 6, 1, 9, 0xFFFFFFFF);
// Curved longitude lines
draw_rect(offset_x + 11, net_offset_y + 5, 1, 11, 0xFFFFFFFF);
draw_rect(offset_x + 23, net_offset_y + 5, 1, 11, 0xFFFFFFFF);
draw_string(offset_x + 40, net_offset_y + 8, "Network", 0xFF000000);
} }
static void control_panel_paint_wallpaper(Window *win) { static void control_panel_paint_wallpaper(Window *win) {
@ -114,6 +236,47 @@ static void control_panel_paint_wallpaper(Window *win) {
draw_button(button_x + 200, button_y, 60, 20, "Grey", false); draw_button(button_x + 200, button_y, 60, 20, "Grey", false);
draw_rect(button_x + 265, button_y + 5, 20, 10, COLOR_GREY); draw_rect(button_x + 265, button_y + 5, 20, 10, COLOR_GREY);
// Pattern section
button_y += 40;
draw_string(offset_x, button_y, "Patterns:", 0xFF000000);
button_y += 20;
// Lumberjack pattern button
draw_button(button_x, button_y, 100, 20, "Lumberjack", false);
// Draw small pattern preview (3x3 repeating)
for (int py = 0; py < 12; py++) {
for (int px = 0; px < 18; px++) {
int cell_x = px % 3;
int cell_y = py % 3;
uint32_t color;
if (cell_x == 1 && cell_y == 1) {
color = 0xFF000000; // Black center
} else if (cell_x == 1 || cell_y == 1) {
color = 0xFF404040; // Dark grey cross
} else {
color = 0xFFDC143C; // Red corners
}
draw_rect(button_x + 110 + px, button_y + 4 + py, 1, 1, color);
}
}
// Blue Diamond pattern button
draw_button(button_x + 145, button_y, 115, 20, "Blue Diamond", false);
// Draw small diamond preview
for (int py = 0; py < 10; py++) {
for (int px = 0; px < 20; px++) {
int cx = px - 10;
int cy = py - 5;
int abs_cx = cx < 0 ? -cx : cx;
int abs_cy = cy < 0 ? -cy : cy;
uint32_t color = (abs_cx + abs_cy <= 5) ? 0xFF0000CD : 0xFFADD8E6;
draw_rect(button_x + 270 + px, button_y + 5 + py, 1, 1, color);
}
}
// Custom color section // Custom color section
button_y += 40; button_y += 40;
draw_string(offset_x, button_y, "Or something custom", 0xFF000000); draw_string(offset_x, button_y, "Or something custom", 0xFF000000);
@ -166,25 +329,115 @@ static void control_panel_paint_wallpaper(Window *win) {
draw_button(button_x, button_y + 25, 70, 20, "Apply", false); draw_button(button_x, button_y + 25, 70, 20, "Apply", false);
} }
static void draw_input_box(int x, int y, int width, const char *text, bool focused, int cursor_pos) {
// Draw box
draw_rect(x, y, width, 18, 0xFFFFFFFF);
draw_rect(x, y, width, 1, COLOR_BLACK);
draw_rect(x, y, 1, 18, COLOR_BLACK);
draw_rect(x + width - 1, y, 1, 18, COLOR_BLACK);
draw_rect(x, y + 17, width, 1, COLOR_BLACK);
// Draw text
uint32_t text_color = focused ? 0xFF0000FF : COLOR_BLACK;
draw_string(x + 3, y + 4, text, text_color);
// Draw cursor if focused
if (focused) {
int cursor_x = x + 3 + cursor_pos * 8;
draw_rect(cursor_x, y + 4, 1, 9, 0xFF0000FF);
}
}
static void control_panel_paint_network(Window *win) {
int offset_x = win->x + 8;
int offset_y = win->y + 30;
// Back button
draw_string(offset_x, offset_y, "< Back", 0xFF000080);
// Network Init Button
draw_string(offset_x, offset_y + 25, "Network:", 0xFF000000);
draw_button(offset_x, offset_y + 45, 100, 22, "Init Network", false);
// Status message
if (net_status[0] != '\0') {
draw_string(offset_x + 110, offset_y + 50, net_status, 0xFF008000);
}
// Set IP Section
int section_y = offset_y + 80;
draw_string(offset_x, section_y, "Set Static IP:", 0xFF000000);
section_y += 20;
// IP input boxes (4 octets)
draw_input_box(offset_x, section_y, 40, ip_1, focused_field == 0, input_cursor);
draw_string(offset_x + 42, section_y + 4, ".", COLOR_BLACK);
draw_input_box(offset_x + 50, section_y, 40, ip_2, focused_field == 1, input_cursor);
draw_string(offset_x + 92, section_y + 4, ".", COLOR_BLACK);
draw_input_box(offset_x + 100, section_y, 40, ip_3, focused_field == 2, input_cursor);
draw_string(offset_x + 142, section_y + 4, ".", COLOR_BLACK);
draw_input_box(offset_x + 150, section_y, 40, ip_4, focused_field == 3, input_cursor);
// Apply IP button
draw_button(offset_x + 200, section_y, 70, 18, "Apply", false);
// Send UDP Section
section_y += 35;
draw_string(offset_x, section_y, "Send UDP Message:", 0xFF000000);
section_y += 20;
draw_string(offset_x, section_y + 4, "IP:", COLOR_BLACK);
draw_input_box(offset_x + 25, section_y, 40, dest_ip_1, focused_field == 4, input_cursor);
draw_string(offset_x + 67, section_y + 4, ".", COLOR_BLACK);
draw_input_box(offset_x + 75, section_y, 40, dest_ip_2, focused_field == 5, input_cursor);
draw_string(offset_x + 117, section_y + 4, ".", COLOR_BLACK);
draw_input_box(offset_x + 125, section_y, 40, dest_ip_3, focused_field == 6, input_cursor);
draw_string(offset_x + 167, section_y + 4, ".", COLOR_BLACK);
draw_input_box(offset_x + 175, section_y, 40, dest_ip_4, focused_field == 7, input_cursor);
section_y += 25;
draw_string(offset_x, section_y + 4, "Port:", COLOR_BLACK);
draw_input_box(offset_x + 40, section_y, 60, udp_port, focused_field == 8, input_cursor);
section_y += 25;
draw_string(offset_x, section_y + 4, "Msg:", COLOR_BLACK);
draw_input_box(offset_x + 40, section_y, 260, udp_message, focused_field == 9, input_cursor);
// Send button
section_y += 25;
draw_button(offset_x, section_y, 80, 22, "Send", false);
}
static void control_panel_paint(Window *win) { static void control_panel_paint(Window *win) {
if (current_view == VIEW_MAIN) { if (current_view == VIEW_MAIN) {
control_panel_paint_main(win); control_panel_paint_main(win);
} else if (current_view == VIEW_WALLPAPER) { } else if (current_view == VIEW_WALLPAPER) {
control_panel_paint_wallpaper(win); control_panel_paint_wallpaper(win);
} else if (current_view == VIEW_NETWORK) {
control_panel_paint_network(win);
} }
} }
static void control_panel_handle_click(Window *win, int x, int y) { static void control_panel_handle_click(Window *win, int x, int y) {
(void)win; // Unused parameter (void)win;
if (current_view == VIEW_MAIN) { if (current_view == VIEW_MAIN) {
int offset_x = 8; int offset_x = 8;
int offset_y = 30; int offset_y = 30;
// Check wallpaper folder click // Check wallpaper button click (icon + text)
if (x >= offset_x + 5 && x < offset_x + 35 && if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= offset_y && y < offset_y + 25) { y >= offset_y && y < offset_y + 25) {
current_view = VIEW_WALLPAPER; current_view = VIEW_WALLPAPER;
focused_field = -1;
}
// Check network button click (icon + text)
int net_offset_y = offset_y + 35;
if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= net_offset_y && y < net_offset_y + 25) {
current_view = VIEW_NETWORK;
focused_field = -1;
} }
} else if (current_view == VIEW_WALLPAPER) { } else if (current_view == VIEW_WALLPAPER) {
int offset_x = 8; int offset_x = 8;
@ -236,6 +489,22 @@ static void control_panel_handle_click(Window *win, int x, int y) {
return; return;
} }
// Pattern section
button_y += 40;
button_y += 20;
// Check Lumberjack pattern button
if (x >= button_x && x < button_x + 100 && y >= button_y && y < button_y + 20) {
graphics_set_bg_pattern(pattern_lumberjack);
return;
}
// Check Blue Diamond pattern button
if (x >= button_x + 145 && x < button_x + 260 && y >= button_y && y < button_y + 20) {
graphics_set_bg_pattern(pattern_blue_diamond);
return;
}
// Custom RGB section // Custom RGB section
button_y += 40; button_y += 40;
button_y += 20; button_y += 20;
@ -275,43 +544,278 @@ static void control_panel_handle_click(Window *win, int x, int y) {
graphics_set_bg_color(parse_rgb_separate(rgb_r, rgb_g, rgb_b)); graphics_set_bg_color(parse_rgb_separate(rgb_r, rgb_g, rgb_b));
return; return;
} }
} else if (current_view == VIEW_NETWORK) {
int offset_x = 8;
int offset_y = 30;
// Back button
if (x >= offset_x && x < offset_x + 40 && y >= offset_y && y < offset_y + 15) {
current_view = VIEW_MAIN;
focused_field = -1;
return;
}
// Init Network button
if (x >= offset_x && x < offset_x + 100 && y >= offset_y + 45 && y < offset_y + 67) {
int result = network_init();
if (result == 0) {
net_status[0] = 'I'; net_status[1] = 'n'; net_status[2] = 'i';
net_status[3] = 't'; net_status[4] = 'e'; net_status[5] = 'd';
net_status[6] = '\0';
} else {
net_status[0] = 'F'; net_status[1] = 'a'; net_status[2] = 'i';
net_status[3] = 'l'; net_status[4] = 'e'; net_status[5] = 'd';
net_status[6] = '\0';
}
return;
}
int section_y = offset_y + 80 + 20;
// IP octet 1
if (x >= offset_x && x < offset_x + 40 && y >= section_y && y < section_y + 18) {
focused_field = 0;
input_cursor = 0;
return;
}
// IP octet 2
if (x >= offset_x + 50 && x < offset_x + 90 && y >= section_y && y < section_y + 18) {
focused_field = 1;
input_cursor = 0;
return;
}
// IP octet 3
if (x >= offset_x + 100 && x < offset_x + 140 && y >= section_y && y < section_y + 18) {
focused_field = 2;
input_cursor = 0;
return;
}
// IP octet 4
if (x >= offset_x + 150 && x < offset_x + 190 && y >= section_y && y < section_y + 18) {
focused_field = 3;
input_cursor = 0;
return;
}
// Apply IP button
if (x >= offset_x + 200 && x < offset_x + 270 && y >= section_y && y < section_y + 18) {
ipv4_address_t ip;
ip.bytes[0] = 0; ip.bytes[1] = 0; ip.bytes[2] = 0; ip.bytes[3] = 0;
// Parse IP octets
for (int i = 0; ip_1[i] && i < 3; i++) {
if (ip_1[i] >= '0' && ip_1[i] <= '9') {
ip.bytes[0] = ip.bytes[0] * 10 + (ip_1[i] - '0');
}
}
for (int i = 0; ip_2[i] && i < 3; i++) {
if (ip_2[i] >= '0' && ip_2[i] <= '9') {
ip.bytes[1] = ip.bytes[1] * 10 + (ip_2[i] - '0');
}
}
for (int i = 0; ip_3[i] && i < 3; i++) {
if (ip_3[i] >= '0' && ip_3[i] <= '9') {
ip.bytes[2] = ip.bytes[2] * 10 + (ip_3[i] - '0');
}
}
for (int i = 0; ip_4[i] && i < 3; i++) {
if (ip_4[i] >= '0' && ip_4[i] <= '9') {
ip.bytes[3] = ip.bytes[3] * 10 + (ip_4[i] - '0');
}
}
network_set_ipv4_address(&ip);
net_status[0] = 'I'; net_status[1] = 'P'; net_status[2] = ' ';
net_status[3] = 's'; net_status[4] = 'e'; net_status[5] = 't';
net_status[6] = '\0';
return;
}
section_y += 35 + 20;
// Dest IP octets
if (x >= offset_x + 25 && x < offset_x + 65 && y >= section_y && y < section_y + 18) {
focused_field = 4;
input_cursor = 0;
return;
}
if (x >= offset_x + 75 && x < offset_x + 115 && y >= section_y && y < section_y + 18) {
focused_field = 5;
input_cursor = 0;
return;
}
if (x >= offset_x + 125 && x < offset_x + 165 && y >= section_y && y < section_y + 18) {
focused_field = 6;
input_cursor = 0;
return;
}
if (x >= offset_x + 175 && x < offset_x + 215 && y >= section_y && y < section_y + 18) {
focused_field = 7;
input_cursor = 0;
return;
}
section_y += 25;
// Port field
if (x >= offset_x + 40 && x < offset_x + 100 && y >= section_y && y < section_y + 18) {
focused_field = 8;
input_cursor = 0;
return;
}
section_y += 25;
// Message field
if (x >= offset_x + 40 && x < offset_x + 300 && y >= section_y && y < section_y + 18) {
focused_field = 9;
input_cursor = 0;
return;
}
section_y += 25;
// Send button
if (x >= offset_x && x < offset_x + 80 && y >= section_y && y < section_y + 22) {
ipv4_address_t dest_ip;
dest_ip.bytes[0] = 0; dest_ip.bytes[1] = 0; dest_ip.bytes[2] = 0; dest_ip.bytes[3] = 0;
// Parse dest IP
for (int i = 0; dest_ip_1[i] && i < 3; i++) {
if (dest_ip_1[i] >= '0' && dest_ip_1[i] <= '9') {
dest_ip.bytes[0] = dest_ip.bytes[0] * 10 + (dest_ip_1[i] - '0');
}
}
for (int i = 0; dest_ip_2[i] && i < 3; i++) {
if (dest_ip_2[i] >= '0' && dest_ip_2[i] <= '9') {
dest_ip.bytes[1] = dest_ip.bytes[1] * 10 + (dest_ip_2[i] - '0');
}
}
for (int i = 0; dest_ip_3[i] && i < 3; i++) {
if (dest_ip_3[i] >= '0' && dest_ip_3[i] <= '9') {
dest_ip.bytes[2] = dest_ip.bytes[2] * 10 + (dest_ip_3[i] - '0');
}
}
for (int i = 0; dest_ip_4[i] && i < 3; i++) {
if (dest_ip_4[i] >= '0' && dest_ip_4[i] <= '9') {
dest_ip.bytes[3] = dest_ip.bytes[3] * 10 + (dest_ip_4[i] - '0');
}
}
// Parse port
int port = 0;
for (int i = 0; udp_port[i] && i < 5; i++) {
if (udp_port[i] >= '0' && udp_port[i] <= '9') {
port = port * 10 + (udp_port[i] - '0');
}
}
// Get message length
int msg_len = 0;
while (udp_message[msg_len] && msg_len < 127) msg_len++;
if (msg_len > 0 && port > 0) {
int result = udp_send_packet(&dest_ip, (uint16_t)port, 54321, udp_message, (size_t)msg_len);
if (result == 0) {
net_status[0] = 'S'; net_status[1] = 'e'; net_status[2] = 'n';
net_status[3] = 't'; net_status[4] = '\0';
} else {
net_status[0] = 'F'; net_status[1] = 'a'; net_status[2] = 'i';
net_status[3] = 'l'; net_status[4] = '\0';
}
}
return;
}
} }
} }
static void control_panel_handle_key(Window *win, char c) { static void control_panel_handle_key(Window *win, char c) {
(void)win; // Unused parameter (void)win;
if (current_view != VIEW_WALLPAPER) return; if (focused_field < 0) return;
if (focused_field < 0) return; // No field focused
// Get the currently focused field buffer if (current_view == VIEW_WALLPAPER) {
char *focused_buffer = NULL; // Get the currently focused field buffer
int max_len = 3; // RGB values are 0-255, max 3 digits char *focused_buffer = NULL;
int max_len = 3; // RGB values are 0-255, max 3 digits
if (focused_field == 0) { if (focused_field == 0) {
focused_buffer = rgb_r; focused_buffer = rgb_r;
} else if (focused_field == 1) { } else if (focused_field == 1) {
focused_buffer = rgb_g; focused_buffer = rgb_g;
} else if (focused_field == 2) { } else if (focused_field == 2) {
focused_buffer = rgb_b; focused_buffer = rgb_b;
} else { } else {
return; return;
}
if (c == '\b') { // Backspace
if (input_cursor > 0) {
input_cursor--;
focused_buffer[input_cursor] = '\0';
} }
} else if (c >= '0' && c <= '9') { // Digits only
if (input_cursor < max_len) { if (c == '\b') { // Backspace
focused_buffer[input_cursor] = c; if (input_cursor > 0) {
input_cursor++; input_cursor--;
focused_buffer[input_cursor] = '\0'; focused_buffer[input_cursor] = '\0';
}
} else if (c >= '0' && c <= '9') { // Digits only
if (input_cursor < max_len) {
focused_buffer[input_cursor] = c;
input_cursor++;
focused_buffer[input_cursor] = '\0';
}
} else if (c == '\t') { // Tab - switch to next field
focused_field = (focused_field + 1) % 3;
input_cursor = 0;
}
} else if (current_view == VIEW_NETWORK) {
char *focused_buffer = NULL;
int max_len = 3; // Default for IP octets
// Select the focused field
if (focused_field == 0) {
focused_buffer = ip_1;
} else if (focused_field == 1) {
focused_buffer = ip_2;
} else if (focused_field == 2) {
focused_buffer = ip_3;
} else if (focused_field == 3) {
focused_buffer = ip_4;
} else if (focused_field == 4) {
focused_buffer = dest_ip_1;
} else if (focused_field == 5) {
focused_buffer = dest_ip_2;
} else if (focused_field == 6) {
focused_buffer = dest_ip_3;
} else if (focused_field == 7) {
focused_buffer = dest_ip_4;
} else if (focused_field == 8) {
focused_buffer = udp_port;
max_len = 5; // Ports up to 65535
} else if (focused_field == 9) {
focused_buffer = udp_message;
max_len = 127; // Message max length
} else {
return;
}
if (c == '\b') { // Backspace
if (input_cursor > 0) {
input_cursor--;
focused_buffer[input_cursor] = '\0';
}
} else if (focused_field <= 8 && c >= '0' && c <= '9') { // Digits only for IP/port
if (input_cursor < max_len) {
focused_buffer[input_cursor] = c;
input_cursor++;
focused_buffer[input_cursor] = '\0';
}
} else if (focused_field == 9 && c >= 32 && c <= 126) { // All printable chars for message
if (input_cursor < max_len) {
focused_buffer[input_cursor] = c;
input_cursor++;
focused_buffer[input_cursor] = '\0';
}
} else if (c == '\t') { // Tab - switch to next field
focused_field = (focused_field + 1) % 10;
input_cursor = 0;
} }
} else if (c == '\t') { // Tab - switch to next field
focused_field = (focused_field + 1) % 3;
input_cursor = 0;
} }
} }
@ -330,6 +834,10 @@ void control_panel_init(void) {
win_control_panel.handle_right_click = NULL; win_control_panel.handle_right_click = NULL;
win_control_panel.buf_len = 0; win_control_panel.buf_len = 0;
win_control_panel.cursor_pos = 0; win_control_panel.cursor_pos = 0;
// Generate patterns
generate_lumberjack_pattern();
generate_blue_diamond_pattern();
} }
void control_panel_reset(void) { void control_panel_reset(void) {

View file

@ -5,6 +5,11 @@
static struct limine_framebuffer *g_fb = NULL; static struct limine_framebuffer *g_fb = NULL;
static uint32_t g_bg_color = 0xFF696969; // Dark gray background static uint32_t g_bg_color = 0xFF696969; // Dark gray background
// Pattern support
#define PATTERN_SIZE 128
static uint32_t g_bg_pattern[PATTERN_SIZE * PATTERN_SIZE];
static bool g_use_pattern = false;
// Dirty rectangle tracking // Dirty rectangle tracking
static DirtyRect g_dirty = {0, 0, 0, 0, false}; static DirtyRect g_dirty = {0, 0, 0, 0, false};
@ -145,11 +150,36 @@ void draw_string(int x, int y, const char *s, uint32_t color) {
void draw_desktop_background(void) { void draw_desktop_background(void) {
if (!g_fb) return; if (!g_fb) return;
draw_rect(0, 0, g_fb->width, g_fb->height, g_bg_color);
if (g_use_pattern) {
// Draw tiled pattern
for (int y = 0; y < (int)g_fb->height; y++) {
for (int x = 0; x < (int)g_fb->width; x++) {
int px = x % PATTERN_SIZE;
int py = y % PATTERN_SIZE;
uint32_t color = g_bg_pattern[py * PATTERN_SIZE + px];
put_pixel(x, y, color);
}
}
} else {
// Draw solid color
draw_rect(0, 0, g_fb->width, g_fb->height, g_bg_color);
}
} }
void graphics_set_bg_color(uint32_t color) { void graphics_set_bg_color(uint32_t color) {
g_bg_color = color; g_bg_color = color;
g_use_pattern = false;
}
void graphics_set_bg_pattern(const uint32_t *pattern) {
if (!pattern) return;
// Copy pattern to internal buffer
for (int i = 0; i < PATTERN_SIZE * PATTERN_SIZE; i++) {
g_bg_pattern[i] = pattern[i];
}
g_use_pattern = true;
} }
// Double buffering functions // Double buffering functions

View file

@ -18,6 +18,7 @@ void draw_char(int x, int y, char c, uint32_t color);
void draw_string(int x, int y, const char *s, uint32_t color); void draw_string(int x, int y, const char *s, uint32_t color);
void draw_desktop_background(void); void draw_desktop_background(void);
void graphics_set_bg_color(uint32_t color); void graphics_set_bg_color(uint32_t color);
void graphics_set_bg_pattern(const uint32_t *pattern); // 128x128 pattern
// Get screen dimensions // Get screen dimensions
int get_screen_width(void); int get_screen_width(void);

View file

@ -6,7 +6,7 @@
static int network_initialized = 0; static int network_initialized = 0;
static mac_address_t our_mac; static mac_address_t our_mac;
static ipv4_address_t our_ip = {{0,0,0,0}}; static ipv4_address_t ip_address = {{0,0,0,0}};
static uint16_t ipv4_id_counter = 0; static uint16_t ipv4_id_counter = 0;
typedef struct { ipv4_address_t ip; mac_address_t mac; uint32_t timestamp; int valid; } arp_cache_entry_t; typedef struct { ipv4_address_t ip; mac_address_t mac; uint32_t timestamp; int valid; } arp_cache_entry_t;
@ -63,8 +63,8 @@ int network_get_mac_address(mac_address_t* mac){
return 0; return 0;
} }
int network_get_ipv4_address(ipv4_address_t* ip){ if(!network_initialized) return -1; *ip=our_ip; return 0; } int network_get_ipv4_address(ipv4_address_t* ip){ if(!network_initialized) return -1; *ip=ip_address; return 0; }
int network_set_ipv4_address(const ipv4_address_t* ip){ if(!network_initialized) return -1; our_ip=*ip; return 0; } int network_set_ipv4_address(const ipv4_address_t* ip){ if(!network_initialized) return -1; ip_address=*ip; return 0; }
int network_send_frame(const void* data,size_t length){ if(!network_initialized) return -1; if(length>ETH_FRAME_MAX_SIZE) return -1; return e1000_send_packet(data,length); } int network_send_frame(const void* data,size_t length){ if(!network_initialized) return -1; if(length>ETH_FRAME_MAX_SIZE) return -1; return e1000_send_packet(data,length); }
@ -102,7 +102,7 @@ void network_process_frames(void){
ip->checksum=checksum; ip->checksum=checksum;
if(checksum==calc){ if(checksum==calc){
int for_our_ip=1; int for_our_ip=1;
for(int i=0;i<4;i++){ if(ip->dest_ip[i]!=our_ip.bytes[i]) { for_our_ip=0; break; } } for(int i=0;i<4;i++){ if(ip->dest_ip[i]!=ip_address.bytes[i]) { for_our_ip=0; break; } }
if(for_our_ip || ip->dest_ip[0]==255){ if(for_our_ip || ip->dest_ip[0]==255){
mac_address_t src_mac; mac_address_t src_mac;
kmemcpy(src_mac.bytes,eth->src_mac,6); kmemcpy(src_mac.bytes,eth->src_mac,6);
@ -128,7 +128,7 @@ int arp_send_request(const ipv4_address_t* target_ip){
arp->proto_len=4; arp->proto_len=4;
arp->opcode=htons(ARP_OP_REQUEST); arp->opcode=htons(ARP_OP_REQUEST);
kmemcpy(arp->sender_mac,our_mac.bytes,6); kmemcpy(arp->sender_mac,our_mac.bytes,6);
kmemcpy(arp->sender_ip,our_ip.bytes,4); kmemcpy(arp->sender_ip,ip_address.bytes,4);
for(int i=0;i<6;i++) arp->target_mac[i]=0; for(int i=0;i<6;i++) arp->target_mac[i]=0;
kmemcpy(arp->target_ip,target_ip->bytes,4); kmemcpy(arp->target_ip,target_ip->bytes,4);
size_t frame_length=sizeof(eth_header_t)+sizeof(arp_header_t); size_t frame_length=sizeof(eth_header_t)+sizeof(arp_header_t);
@ -153,7 +153,7 @@ void arp_process_packet(const arp_header_t* arp,size_t length){
arp_cache_add(&sender_ip,&sender_mac); arp_cache_add(&sender_ip,&sender_mac);
if(opcode==ARP_OP_REQUEST){ if(opcode==ARP_OP_REQUEST){
int is_for_us=1; int is_for_us=1;
for(int i=0;i<4;i++){ if(arp->target_ip[i]!=our_ip.bytes[i]) { is_for_us=0; break; } } for(int i=0;i<4;i++){ if(arp->target_ip[i]!=ip_address.bytes[i]) { is_for_us=0; break; } }
if(is_for_us){ if(is_for_us){
uint8_t frame[ETH_FRAME_MAX_SIZE]; uint8_t frame[ETH_FRAME_MAX_SIZE];
eth_header_t* eth=(eth_header_t*)frame; eth_header_t* eth=(eth_header_t*)frame;
@ -167,7 +167,7 @@ void arp_process_packet(const arp_header_t* arp,size_t length){
r->proto_len=4; r->proto_len=4;
r->opcode=htons(ARP_OP_REPLY); r->opcode=htons(ARP_OP_REPLY);
kmemcpy(r->sender_mac,our_mac.bytes,6); kmemcpy(r->sender_mac,our_mac.bytes,6);
kmemcpy(r->sender_ip,our_ip.bytes,4); kmemcpy(r->sender_ip,ip_address.bytes,4);
kmemcpy(r->target_mac,arp->sender_mac,6); kmemcpy(r->target_mac,arp->sender_mac,6);
kmemcpy(r->target_ip,arp->sender_ip,4); kmemcpy(r->target_ip,arp->sender_ip,4);
size_t frame_length=sizeof(eth_header_t)+sizeof(arp_header_t); size_t frame_length=sizeof(eth_header_t)+sizeof(arp_header_t);
@ -197,7 +197,7 @@ int ipv4_send_packet(const ipv4_address_t* dest_ip,uint8_t protocol,const void*
ip->ttl=64; ip->ttl=64;
ip->protocol=protocol; ip->protocol=protocol;
ip->checksum=0; ip->checksum=0;
kmemcpy(ip->src_ip,our_ip.bytes,4); kmemcpy(ip->src_ip,ip_address.bytes,4);
kmemcpy(ip->dest_ip,dest_ip->bytes,4); kmemcpy(ip->dest_ip,dest_ip->bytes,4);
ip->checksum=ipv4_checksum(ip); ip->checksum=ipv4_checksum(ip);
kmemcpy(ip_payload,data,data_length); kmemcpy(ip_payload,data,data_length);
@ -222,7 +222,7 @@ int ipv4_send_packet_to_mac(const ipv4_address_t* dest_ip,const mac_address_t* d
ip->ttl=64; ip->ttl=64;
ip->protocol=protocol; ip->protocol=protocol;
ip->checksum=0; ip->checksum=0;
kmemcpy(ip->src_ip,our_ip.bytes,4); kmemcpy(ip->src_ip,ip_address.bytes,4);
kmemcpy(ip->dest_ip,dest_ip->bytes,4); kmemcpy(ip->dest_ip,dest_ip->bytes,4);
ip->checksum=ipv4_checksum(ip); ip->checksum=ipv4_checksum(ip);
kmemcpy(ip_payload,data,data_length); kmemcpy(ip_payload,data,data_length);
@ -405,10 +405,10 @@ static void dhcp_udp_callback(const ipv4_address_t* src_ip,uint16_t src_port,con
if(dhcp_server_id!=0) dhcp_state=1; if(dhcp_server_id!=0) dhcp_state=1;
} else if(mtype==DHCP_MSG_ACK){ } else if(mtype==DHCP_MSG_ACK){
uint32_t yi_host=ntohl32(pkt->yiaddr); uint32_t yi_host=ntohl32(pkt->yiaddr);
our_ip.bytes[0]=(uint8_t)((yi_host>>24)&0xFF); ip_address.bytes[0]=(uint8_t)((yi_host>>24)&0xFF);
our_ip.bytes[1]=(uint8_t)((yi_host>>16)&0xFF); ip_address.bytes[1]=(uint8_t)((yi_host>>16)&0xFF);
our_ip.bytes[2]=(uint8_t)((yi_host>>8)&0xFF); ip_address.bytes[2]=(uint8_t)((yi_host>>8)&0xFF);
our_ip.bytes[3]=(uint8_t)(yi_host&0xFF); ip_address.bytes[3]=(uint8_t)(yi_host&0xFF);
dhcp_state=2; dhcp_state=2;
} else if(mtype==DHCP_MSG_NAK){ } else if(mtype==DHCP_MSG_NAK){
dhcp_state=-1; dhcp_state=-1;