From 3b40d307444114270e4d8a9701d91dd12a73fab4 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Mon, 26 Jan 2026 12:44:50 -0600 Subject: [PATCH] feat: migrate to a daemon to support windowing in future. allow to run without attached console --- src/main.rs | 35 +++++++++++++++++++++++++---------- src/message.rs | 4 +++- src/state.rs | 13 ++++++++++++- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/main.rs b/src/main.rs index e4515aa..9dff854 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + mod components; mod constants; mod file; @@ -18,7 +20,7 @@ use crate::message::Message; use crate::state::State; pub fn main() -> iced::Result { - iced::application(boot, update, view) + iced::daemon(boot, update, view) .subscription(subscription) .font(constants::CUSTOM_FONT_BYTES) .theme(theme) @@ -26,15 +28,16 @@ pub fn main() -> iced::Result { default_font: constants::CUSTOM_FONT, ..Default::default() }) - .window(window::Settings { - icon: Some(icon::from_file_data(constants::ICON_BYTES, None).expect("Failed to load icon")), - ..window::Settings::default() - }) .run() } -fn boot() -> State { - state::State::new() +fn boot() -> (State, Task) { + let (id, open) = window::open(window::Settings { + icon: Some(icon::from_file_data(constants::ICON_BYTES, None).expect("Failed to load icon")), + ..window::Settings::default() + }); + + (state::State::new(id), open.map(Message::WindowOpened)) } fn update(state: &mut State, message: Message) -> Task { @@ -46,10 +49,21 @@ fn update(state: &mut State, message: Message) -> Task { Message::ViewActionSelected(action) => handler::view_action(state, action), Message::FileOpened(result) => handler::opened_file(state, result), Message::FileSaved(result) => handler::saved_file(state, result), + Message::WindowOpened(id) => { + state.set_window_id(id); + Task::none() + } + Message::WindowClosed(id) => { + if state.window_id() == Some(id) { + iced::exit() + } else { + Task::none() + } + } } } -fn view(state: &State) -> Element<'_, Message> { +fn view(state: &State, _id: iced::window::Id) -> Element<'_, Message> { let current_file = state.active_file(); column![ @@ -62,8 +76,9 @@ fn view(state: &State) -> Element<'_, Message> { } fn subscription(_state: &State) -> Subscription { - event::listen_with(|e, _status, _win| -> Option { + event::listen_with(|e, _status, win| -> Option { match e { + iced::Event::Window(window::Event::Closed) => Some(Message::WindowClosed(win)), iced::Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, .. }) => { for vb in key_bindings::ALL { if vb.should_handle(&key, &modifiers) { @@ -78,7 +93,7 @@ fn subscription(_state: &State) -> Subscription { }) } -fn theme(_state: &State) -> Theme { +fn theme(_state: &State, _id: iced::window::Id) -> Theme { Theme::custom( "Win11 Dark", Palette { diff --git a/src/message.rs b/src/message.rs index 2186d15..356ddeb 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,6 +1,6 @@ use std::{fmt::Display, path::PathBuf}; -use iced::widget::text_editor; +use iced::{widget::text_editor, window}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FileAction { @@ -63,6 +63,8 @@ impl Display for ViewAction { #[derive(Debug, Clone)] pub enum Message { + WindowOpened(window::Id), + WindowClosed(window::Id), Edit(text_editor::Action), FileActionSelected(FileAction), ViewActionSelected(ViewAction), diff --git a/src/state.rs b/src/state.rs index 8d9ad96..dea611f 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use iced::widget::text_editor; +use iced::window; use crate::message::{FileAction, ViewAction}; use crate::{constants, file}; @@ -14,6 +15,7 @@ pub enum Mode { #[derive(Default)] pub struct State { + window_id: Option, mode: Mode, files: Vec, current_file: usize, @@ -23,10 +25,11 @@ pub struct State { } impl State { - pub fn new() -> Self { + pub fn new(window_id: window::Id) -> Self { let default_file = file::File::default(); Self { + window_id: Some(window_id), files: vec![default_file], current_file: 0, editor_font_size: constants::DEFAULT_EDITOR_FONT_SIZE, @@ -133,6 +136,10 @@ impl State { self.mode } + pub fn window_id(&self) -> Option { + self.window_id + } + pub fn font_size(&self) -> u32 { self.editor_font_size } @@ -144,4 +151,8 @@ impl State { pub fn selected_view_action(&self) -> Option { self.selected_view_action } + + pub fn set_window_id(&mut self, id: window::Id) { + self.window_id = Some(id) + } }