Skip to content

Add icon to titlebar #715

Closed
Closed

Description

@jermanuts

Is there an existing issue for this?

  • I have searched the existing issues.

Describe the solution you'd like

An icon in the titlebar

Image

https://docs.iced.rs/iced/window/struct.Icon.html

Relevant issue iced-rs/iced#587

Is your feature request related to a problem?

yes, there's no icon in titlebar for Windows

Activity

  1. GyulyVGC commented on Feb 14, 2025

    @GyulyVGC
    Owner

    Thanks for the suggestion

  2. ZeroDot1 commented on Feb 15, 2025

    @ZeroDot1
    Contributor
    use iced::window;
    use iced::window::icon;
    
    // Assuming you have an icon file named "app_icon.png" in the root of your project
    const ICON_BYTES: &[u8] = include_bytes!("../app_icon.png");
    
    fn main() -> iced::Result {
        // Load the icon from the raw bytes
        let app_icon = icon::from_file_data(ICON_BYTES, None).expect("Failed to load icon");
    
        let configs = CONFIGS.clone();
        let boot_task_chain = handle_cli_args();
    
        let configs1 = Arc::new(Mutex::new(configs));
        let configs2 = configs1.clone();
    
        let newer_release_available1 = Arc::new(Mutex::new(None));
        let newer_release_available2 = newer_release_available1.clone();
    
        // ... (rest of your setup code)
    
        let ConfigWindow { size, position, .. } = configs1.lock().unwrap().window;
    
        application(SNIFFNET_TITLECASE, Sniffer::update, Sniffer::view)
            .settings(Settings {
                // id needed for Linux Wayland; should match StartupWMClass in .desktop file; see issue #292
                id: Some(String::from(SNIFFNET_LOWERCASE)),
                fonts: vec![
                    Cow::Borrowed(SARASA_MONO_BYTES),
                    Cow::Borrowed(SARASA_MONO_BOLD_BYTES),
                    Cow::Borrowed(ICONS_BYTES),
                ],
                default_font: Font::with_name(FONT_FAMILY_NAME),
                default_text_size: Pixels(FONT_SIZE_BODY),
                antialiasing: false,
            })
            .window(window::Settings {
                size: size.to_size(), // start size
                position: position.to_position(),
                min_size: None, // Some(ConfigWindow::MIN_SIZE.to_size()), // min size allowed
                max_size: None,
                visible: true,
                resizable: true,
                decorations: true,
                transparent: false,
                icon: Some(app_icon), // Set the icon here
                #[cfg(target_os = "linux")]
                platform_specific: PlatformSpecific {
                    application_id: String::from(SNIFFNET_LOWERCASE),
                    ..PlatformSpecific::default()
                },
                exit_on_close_request: false,
                ..Default::default()
            })
            .subscription(Sniffer::subscription)
            .theme(Sniffer::theme)
            .scale_factor(Sniffer::scale_factor)
            .run_with(move || {
                (
                    Sniffer::new(&configs1, newer_release_available1),
                    boot_task_chain,
                )
            })
    }
  3. GyulyVGC commented on Feb 15, 2025

    @GyulyVGC
    Owner

    Yes, I just have to verify whether it correctly sets the icon.
    I remember I tried in the past without success, but probably this was fixed in newer iced versions.

  4. ZeroDot1 commented on Feb 15, 2025

    @ZeroDot1
    Contributor

    Image

    OK, I quickly implemented it, it works as shown in the screenshot. the best way is to integrate the function into the main rs.

    Here is the code:

    cargo:
    iced = { version = "0.13.1", features = ["tokio", "svg", "advanced", "lazy", "image"] }

    main.rs

    //! Module containing the entry point of application execution.
    
    #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
    
    use std::borrow::Cow;
    use std::sync::{Arc, Mutex};
    use std::{panic, process, thread};
    
    #[cfg(target_os = "linux")]
    use iced::window::settings::PlatformSpecific;
    use iced::{application, window, Font, Pixels, Settings};
    
    use chart::types::chart_type::ChartType;
    use chart::types::traffic_chart::TrafficChart;
    use cli::handle_cli_args;
    use configs::types::config_device::ConfigDevice;
    use configs::types::config_settings::ConfigSettings;
    use gui::pages::types::running_page::RunningPage;
    use gui::sniffer::Sniffer;
    use gui::styles::style_constants::FONT_SIZE_BODY;
    use gui::styles::types::style_type::StyleType;
    use gui::types::runtime_data::RunTimeData;
    use networking::types::byte_multiple::ByteMultiple;
    use networking::types::info_traffic::InfoTraffic;
    use networking::types::ip_version::IpVersion;
    use networking::types::protocol::Protocol;
    use networking::types::service::Service;
    use report::types::report_sort_type::ReportSortType;
    use translations::types::language::Language;
    use utils::formatted_strings::print_cli_welcome_message;
    
    use crate::configs::types::config_window::{ConfigWindow, ToPosition, ToSize};
    use crate::configs::types::configs::{Configs, CONFIGS};
    use crate::gui::sniffer::FONT_FAMILY_NAME;
    use crate::gui::styles::style_constants::{ICONS_BYTES, SARASA_MONO_BOLD_BYTES, SARASA_MONO_BYTES};
    use crate::secondary_threads::check_updates::set_newer_release_status;
    
    mod chart;
    mod cli;
    mod configs;
    mod countries;
    mod gui;
    mod mmdb;
    mod networking;
    mod notifications;
    mod report;
    mod secondary_threads;
    mod translations;
    mod utils;
    
    pub const SNIFFNET_LOWERCASE: &str = "sniffnet";
    pub const SNIFFNET_TITLECASE: &str = "Sniffnet";
    
    // Load the icon file as raw bytes
    const APP_ICON_BYTES: &[u8] = include_bytes!("app_icon.png");
    
    /// Entry point of application execution
    ///
    /// It initializes shared variables and loads configuration parameters
    pub fn main() -> iced::Result {
        #[cfg(all(windows, not(debug_assertions)))]
        let _gag1: gag::Redirect<std::fs::File>;
        #[cfg(all(windows, not(debug_assertions)))]
        let _gag2: gag::Redirect<std::fs::File>;
        #[cfg(all(windows, not(debug_assertions)))]
        if let Some((gag1, gag2)) = utils::formatted_strings::redirect_stdout_stderr_to_file() {
            _gag1 = gag1;
            _gag2 = gag2;
        }
    
        let configs = CONFIGS.clone();
        let boot_task_chain = handle_cli_args();
    
        let configs1 = Arc::new(Mutex::new(configs));
        let configs2 = configs1.clone();
    
        let newer_release_available1 = Arc::new(Mutex::new(None));
        let newer_release_available2 = newer_release_available1.clone();
    
        // Kill the main thread as soon as a secondary thread panics
        let orig_hook = panic::take_hook();
        panic::set_hook(Box::new(move |panic_info| {
            // Invoke the default handler and exit the process
            orig_hook(panic_info);
            process::exit(1);
        }));
    
        // Gracefully close the app when receiving SIGINT, SIGTERM, or SIGHUP
        ctrlc::set_handler(move || {
            configs2.lock().unwrap().clone().store();
            process::exit(130);
        })
        .expect("Error setting Ctrl-C handler");
    
        thread::Builder::new()
            .name("thread_check_updates".to_string())
            .spawn(move || {
                set_newer_release_status(&newer_release_available2);
            })
            .unwrap();
    
        print_cli_welcome_message();
    
        let ConfigWindow { size, position, .. } = configs1.lock().unwrap().window;
    
        // Load the application icon
        let app_icon = window::icon::from_file_data(APP_ICON_BYTES, None).expect("Failed to load app icon");
    
        application(SNIFFNET_TITLECASE, Sniffer::update, Sniffer::view)
            .settings(Settings {
                // ID needed for Linux Wayland; should match StartupWMClass in .desktop file; see issue #292
                id: Some(String::from(SNIFFNET_LOWERCASE)),
                fonts: vec![
                    Cow::Borrowed(SARASA_MONO_BYTES),
                    Cow::Borrowed(SARASA_MONO_BOLD_BYTES),
                    Cow::Borrowed(ICONS_BYTES),
                ],
                default_font: Font::with_name(FONT_FAMILY_NAME),
                default_text_size: Pixels(FONT_SIZE_BODY),
                antialiasing: false,
            })
            .window(window::Settings {
                size: size.to_size(), // Start size
                position: position.to_position(),
                min_size: None, // Some(ConfigWindow::MIN_SIZE.to_size()), // Min size allowed
                max_size: None,
                visible: true,
                resizable: true,
                decorations: true,
                transparent: false,
                icon: Some(app_icon), // Set the application icon here
                #[cfg(target_os = "linux")]
                platform_specific: PlatformSpecific {
                    application_id: String::from(SNIFFNET_LOWERCASE),
                    ..PlatformSpecific::default()
                },
                exit_on_close_request: false,
                ..Default::default()
            })
            .subscription(Sniffer::subscription)
            .theme(Sniffer::theme)
            .scale_factor(Sniffer::scale_factor)
            .run_with(move || {
                (
                    Sniffer::new(&configs1, newer_release_available1),
                    boot_task_chain,
                )
            })
    }
  5. GyulyVGC commented on Feb 15, 2025

    @GyulyVGC
    Owner

    Awesome, thanks. Feel free to send a PR 😁

  6. ZeroDot1 commented on Feb 15, 2025

    @ZeroDot1
    Contributor

    Done via: #717

  7. added a commit that references this issue on Feb 16, 2025
    253da11
  8. self-assigned this
    on Feb 16, 2025
  9. added this to the v1.4.0 milestone on Feb 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature, request, or improvement

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions