Files
MontaukOS/programs/src/login/login.hpp
T

156 lines
5.3 KiB
C++

/*
* login.hpp
* Shared types and helpers for the MontaukOS login screen
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <cstdint>
#include <montauk/syscall.h>
#include <montauk/string.h>
#include <montauk/heap.h>
#include <montauk/user.h>
#include <montauk/config.h>
#include <gui/gui.hpp>
#include <gui/framebuffer.hpp>
#include <gui/draw.hpp>
#include <gui/font.hpp>
#include <gui/canvas.hpp>
#include <gui/mtk/theme.hpp>
#include <gui/mtk/widgets.hpp>
extern "C" {
unsigned char* stbi_load_from_memory(const unsigned char* buffer, int len,
int* x, int* y, int* channels_in_file,
int desired_channels);
void stbi_image_free(void* retval_from_stbi_load);
}
enum LoginMode {
MODE_FIRST_BOOT,
MODE_LOGIN,
};
struct LoginState {
gui::Framebuffer fb;
int screen_w, screen_h;
LoginMode mode;
int active_field;
char username[32];
int username_len;
char display_name[64];
int display_name_len;
char password[64];
int password_len;
char confirm[64];
int confirm_len;
char error_msg[128];
bool show_error;
montauk::abi::MouseState mouse;
uint8_t prev_buttons;
gui::mtk::TextInputState username_input;
gui::mtk::TextInputState display_name_input;
gui::mtk::TextInputState password_input;
gui::mtk::TextInputState confirm_input;
uint32_t* bg_wallpaper;
int bg_wallpaper_w, bg_wallpaper_h;
bool has_wallpaper;
gui::mtk::Theme theme;
// Packed scratch buffer used only when the framebuffer pitch differs from
// width*4, since Canvas assumes a tightly packed buffer. When pitch is
// already packed we draw straight into the framebuffer back buffer.
uint32_t* compose;
};
inline constexpr gui::Color BG_COLOR = gui::Color::from_rgb(0x00, 0x00, 0x00);
inline constexpr gui::Color CARD_BG = gui::colors::WINDOW_BG;
inline constexpr gui::Color CARD_BORDER = gui::colors::BORDER;
inline constexpr gui::Color TITLEBAR_BG = gui::colors::TITLEBAR_BG;
inline constexpr gui::Color FOOTER_BG = gui::Color::from_rgb(0xF7, 0xF7, 0xF7);
inline constexpr gui::Color FIELD_BG = gui::colors::WHITE;
inline constexpr gui::Color FIELD_BG_ACTIVE = gui::Color::from_rgb(0xFA, 0xFC, 0xFF);
inline constexpr gui::Color FIELD_BORDER = gui::colors::BORDER;
inline constexpr gui::Color FIELD_HOVER = gui::Color::from_rgb(0xB7, 0xC7, 0xE8);
inline constexpr gui::Color FIELD_ACTIVE = gui::colors::ACCENT;
inline constexpr gui::Color BTN_COLOR = gui::colors::ACCENT;
inline constexpr gui::Color BTN_HOVER = gui::Color::from_rgb(0x2B, 0x6B, 0xE0);
inline constexpr gui::Color BTN_TEXT = gui::colors::WHITE;
inline constexpr gui::Color SECONDARY_BTN_BG = gui::Color::from_rgb(0xE8, 0xE8, 0xE8);
inline constexpr gui::Color SECONDARY_BTN_HOVER = gui::Color::from_rgb(0xDC, 0xDC, 0xDC);
inline constexpr gui::Color SECONDARY_BTN_BORDER = gui::colors::BORDER;
inline constexpr gui::Color TEXT_COLOR = gui::colors::TEXT_COLOR;
inline constexpr gui::Color LABEL_COLOR = gui::Color::from_rgb(0x66, 0x66, 0x66);
inline constexpr gui::Color ERROR_COLOR = gui::Color::from_rgb(0xC0, 0x33, 0x33);
inline constexpr gui::Color FIELD_SEL_BG = gui::Color::from_rgb(0xB0, 0xD0, 0xF0);
inline constexpr int CARD_W = 432;
inline constexpr int TITLEBAR_H = 30;
inline constexpr int FOOTER_H = 58;
inline constexpr int FIELD_H = 34;
inline constexpr int FIELD_PAD = 10;
inline constexpr int BTN_H = 30;
inline constexpr int LABEL_GAP = 4;
inline constexpr int CONTENT_PAD_X = 24;
inline constexpr int CONTENT_TOP_PAD = 18;
inline constexpr int BODY_BOTTOM_PAD = 18;
inline constexpr int FIELD_GAP = 12;
inline constexpr int POWER_BTN_W = 104;
inline constexpr int POWER_BTN_GAP = 8;
inline constexpr int FOOTER_PAD = 16;
struct LoginLayout {
gui::Rect card;
gui::Rect titlebar;
gui::Rect footer;
gui::Rect username_field;
gui::Rect display_name_field;
gui::Rect password_field;
gui::Rect confirm_field;
gui::Rect submit_button;
gui::Rect shutdown_button;
gui::Rect reboot_button;
int content_x;
int content_w;
int heading_y;
int subtitle_y;
int error_y;
const char* window_title;
const char* heading;
const char* subtitle;
const char* submit_label;
};
struct LoginField {
char* text;
int* len;
int cap; // full buffer size (text capacity incl. null)
bool masked;
gui::mtk::TextInputState* state;
};
bool load_login_wallpaper(LoginState* ls);
LoginField get_field(LoginState* ls, int field);
LoginLayout layout_login_screen(LoginState* ls);
void draw_login_screen(LoginState* ls);
int max_fields(LoginState* ls);
bool try_first_boot_submit(LoginState* ls);
bool try_login(LoginState* ls);
void handle_key(LoginState* ls, const montauk::abi::KeyEvent& key);
void handle_mouse(LoginState* ls);
// Graceful shutdown view (login_shutdown.cpp). draw_shutdown_screen paints the
// status card; perform_graceful_shutdown runs the staged power-off (Bluetooth
// teardown, filesystem flush) and finally issues the ACPI power-off / reset, so
// it never returns. `action` is montauk::abi::POWER_REQ_SHUTDOWN or POWER_REQ_REBOOT.
void draw_shutdown_screen(LoginState* ls, const char* heading, const char* status);
[[noreturn]] void perform_graceful_shutdown(LoginState* ls, int action);