kael 0.2.0

GPU-accelerated native UI framework for Rust — build desktop apps with Metal, DirectX, and Vulkan rendering
Documentation
use windows::Win32::{
    Foundation::*, Networking::NetworkListManager::*, System::Com::*, UI::WindowsAndMessaging::*,
};
use windows_core::Interface;

use crate::NetworkStatus;

use super::events::WM_GPUI_NETWORK_CHANGE;

pub(crate) fn query_network_status() -> NetworkStatus {
    unsafe {
        let manager: Result<INetworkListManager, _> =
            CoCreateInstance(&NetworkListManager, None, CLSCTX_ALL);
        match manager {
            Ok(manager) => match manager.GetConnectivity() {
                Ok(connectivity) => {
                    let has_ipv4 = (connectivity.0 & NLM_CONNECTIVITY_IPV4_INTERNET.0) != 0;
                    let has_ipv6 = (connectivity.0 & NLM_CONNECTIVITY_IPV6_INTERNET.0) != 0;
                    if has_ipv4 || has_ipv6 {
                        NetworkStatus::Online
                    } else {
                        NetworkStatus::Offline
                    }
                }
                Err(_) => NetworkStatus::Online,
            },
            Err(_) => NetworkStatus::Online,
        }
    }
}

pub(crate) fn start_network_monitoring(platform_hwnd: HWND, _validation_number: usize) {
    let hwnd_raw = platform_hwnd.0 as usize;
    std::thread::Builder::new()
        .name("NetworkMonitor".to_owned())
        .spawn(move || {
            let platform_hwnd = HWND(hwnd_raw as *mut _);
            unsafe {
                let _ = CoInitializeEx(None, COINIT_MULTITHREADED);
            }
            let manager: Result<INetworkListManager, _> =
                unsafe { CoCreateInstance(&NetworkListManager, None, CLSCTX_ALL) };
            let Ok(manager) = manager else {
                log::warn!("Failed to create INetworkListManager for monitoring");
                return;
            };
            let cpc: Result<IConnectionPointContainer, _> = manager.cast();
            let Ok(cpc) = cpc else {
                log::warn!("Failed to get IConnectionPointContainer");
                return;
            };
            let cp = unsafe { cpc.FindConnectionPoint(&INetworkListManagerEvents::IID) };
            let Ok(cp) = cp else {
                log::warn!("Failed to find INetworkListManagerEvents connection point");
                return;
            };
            let sink = NetworkEventSink { platform_hwnd };
            let sink: INetworkListManagerEvents = sink.into();
            let cookie = unsafe { cp.Advise(&sink) };
            let Ok(_cookie) = cookie else {
                log::warn!("Failed to advise network events");
                return;
            };

            let mut msg = MSG::default();
            loop {
                let result = unsafe { GetMessageW(&mut msg, None, 0, 0) };
                if !result.as_bool() {
                    break;
                }
                unsafe {
                    DispatchMessageW(&msg);
                }
            }
        })
        .ok();
}

#[windows::core::implement(INetworkListManagerEvents)]
struct NetworkEventSink {
    platform_hwnd: HWND,
}

impl INetworkListManagerEvents_Impl for NetworkEventSink_Impl {
    fn ConnectivityChanged(&self, _newconnectivity: NLM_CONNECTIVITY) -> windows::core::Result<()> {
        unsafe {
            let _ = PostMessageW(
                Some(self.platform_hwnd),
                WM_GPUI_NETWORK_CHANGE,
                WPARAM(0),
                LPARAM(0),
            );
        }
        Ok(())
    }
}