156 lines
5.3 KiB
C++
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);
|