From 9a36e1c4f8d39bf970597dbbb1183dfe815d3059 Mon Sep 17 00:00:00 2001 From: yukirij Date: Thu, 12 Dec 2024 01:07:40 -0800 Subject: [PATCH] Modify window handling. --- Cargo.toml | 6 + doc/design/network/api_control.md | 30 +++ doc/design/network/srv.md | 4 + src/bin/client.rs | 6 +- src/system/api/mod.rs | 6 + src/system/api_control/mod.rs | 74 ++++++ src/system/api_device/mod.rs | 0 src/system/app/context/launcher.rs | 11 + src/system/app/context/mod.rs | 5 + src/system/app/mod.rs | 23 ++ src/system/audio/mod.rs | 6 + src/system/control/mod.rs | 6 + src/system/input/mod.rs | 6 + src/system/mod.rs | 10 +- src/system/network/mod.rs | 6 + src/system/query.rs | 2 + src/system/scene/entity/camera.rs | 9 + src/system/scene/entity/mod.rs | 1 + src/system/scene/mod.rs | 8 + src/system/storage/mod.rs | 6 + src/system/supervisor/mod.rs | 6 + src/system/video/device/mod.rs | 4 + .../video/{internal/mod.rs => internal.rs} | 12 + src/system/video/mod.rs | 16 +- src/system/video/query.rs | 25 ++ src/system/window/config.rs | 6 +- src/system/window/display.rs | 198 +++++++++++++++ .../window/{internal/mod.rs => internal.rs} | 240 +++++++++--------- src/system/window/internal/display.rs | 37 --- src/system/window/layout.rs | 13 +- src/system/window/mod.rs | 7 +- src/system/window/query.rs | 42 ++- src/system/window/windowhandle.rs | 13 + src/system/window/winproc.rs | 166 ++++++++++++ 34 files changed, 833 insertions(+), 177 deletions(-) create mode 100644 doc/design/network/api_control.md create mode 100644 doc/design/network/srv.md create mode 100644 src/system/api_control/mod.rs create mode 100644 src/system/api_device/mod.rs create mode 100644 src/system/app/context/launcher.rs create mode 100644 src/system/app/context/mod.rs create mode 100644 src/system/app/mod.rs create mode 100644 src/system/scene/entity/camera.rs create mode 100644 src/system/scene/entity/mod.rs create mode 100644 src/system/video/device/mod.rs rename src/system/video/{internal/mod.rs => internal.rs} (72%) create mode 100644 src/system/window/display.rs rename src/system/window/{internal/mod.rs => internal.rs} (64%) delete mode 100644 src/system/window/internal/display.rs create mode 100644 src/system/window/windowhandle.rs create mode 100644 src/system/window/winproc.rs diff --git a/Cargo.toml b/Cargo.toml index 888cb47..cc8b1d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,9 @@ crossbeam = "0.8.4" vulkano = "0.34.1" glam = "0.29.2" +egui = "0.29.1" + +cpal = "0.15.3" pool = { git = "https://git.tsukiyo.org/Utility/pool" } @@ -19,7 +22,10 @@ windows = { version = "0.58.0", features = [ "Win32_UI_WindowsAndMessaging", "Win32_Graphics_Gdi", "Win32_UI_Input", + "Win32_System_Registry", "Win32_System_Threading", + "Win32_Devices_DeviceAndDriverInstallation", + "Win32_Devices_Display", ] } widestring = "1.1.0" diff --git a/doc/design/network/api_control.md b/doc/design/network/api_control.md new file mode 100644 index 0000000..caf57d4 --- /dev/null +++ b/doc/design/network/api_control.md @@ -0,0 +1,30 @@ +# Control API + +## Packet + +``` + +``` + +### Encryption + +## Commnad + +Each packet may provide up to 62 commands. + +``` + +``` + +### OpCode + + - (0) Info + - (1) Get + - (2) Set + - (3) Add + +### Code + +### Channel + +### Value diff --git a/doc/design/network/srv.md b/doc/design/network/srv.md new file mode 100644 index 0000000..1f24d0d --- /dev/null +++ b/doc/design/network/srv.md @@ -0,0 +1,4 @@ +# SRV Records + + - _donten._tcp.example.com + - _donten._udp.example.com diff --git a/src/bin/client.rs b/src/bin/client.rs index c341c4f..3d82688 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -18,12 +18,12 @@ fn main() sys_win.create(donten::WindowConfig { x: CW_USEDEFAULT, y: CW_USEDEFAULT, width: 640, height: 480, - visible: true, - resize: false, caption: true, sysmenu: false, + resize: false, private: false, - title: "Hello".to_string(), context: None, }).ok(); std::thread::park(); + + // Handle command queries. } diff --git a/src/system/api/mod.rs b/src/system/api/mod.rs index 8f6482c..5bd833e 100644 --- a/src/system/api/mod.rs +++ b/src/system/api/mod.rs @@ -14,3 +14,9 @@ impl Subsystem for APIManager { Err(Error::new()) } } + +impl From> for APIManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/api_control/mod.rs b/src/system/api_control/mod.rs new file mode 100644 index 0000000..e441523 --- /dev/null +++ b/src/system/api_control/mod.rs @@ -0,0 +1,74 @@ +#[derive(Clone, Copy)] +enum OpCode { + None, + Set, + Add, + Get, +} + +struct Command { + op:OpCode, + code:u16, + channel:u16, + value:i32, +} + +struct Endpoint { + key:[u8;4], + secret:[u8;12], + mask:[u8;508], +} +impl Endpoint { + fn parse(&self, data:&[u8]) -> Result,()> + { + if data.len() == 512 { + let mut commands = Vec::new(); + + let key :[u8;4] = data[0..4].try_into().unwrap_or_default(); + let secret :[u8;12] = data[4..16].try_into().unwrap_or_default(); + + if key == self.key && secret == self.secret { + let mut has_next = true; + let mut index = 16; + while index < 512 && has_next { + let data :[u8;8] = data[index..index+8].try_into().unwrap_or_default(); + + let op = match data[0] & 0x7 { + 1 => OpCode::Get, + 2 => OpCode::Set, + 3 => OpCode::Add, + _ => OpCode::None, + }; + + match op { + OpCode::None => { has_next = false; } + _ => { + let code = (((data[1] as u16) << 8) + (data[0] as u16)) >> 3; + let channel = ((data[3] as u16) << 8) + (data[2] as u16); + + let value = (data[7] as i32) << 24 + + (data[6] as i32) << 16 + + (data[5] as i32) << 8 + + (data[4] as i32); + + commands.push(Command { + op, + code, + channel, + value, + }); + } + } + + index += 8; + } + + Ok(commands) + } else { + Err(()) + } + } else { + Err(()) + } + } +} diff --git a/src/system/api_device/mod.rs b/src/system/api_device/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/system/app/context/launcher.rs b/src/system/app/context/launcher.rs new file mode 100644 index 0000000..ef9ad16 --- /dev/null +++ b/src/system/app/context/launcher.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct Launcher { + +} +impl Launcher { + +} +impl Context for Launcher { + +} diff --git a/src/system/app/context/mod.rs b/src/system/app/context/mod.rs new file mode 100644 index 0000000..e497920 --- /dev/null +++ b/src/system/app/context/mod.rs @@ -0,0 +1,5 @@ +pub trait Context { + fn draw() { } +} + +mod launcher; use launcher::Launcher; diff --git a/src/system/app/mod.rs b/src/system/app/mod.rs new file mode 100644 index 0000000..0882bd6 --- /dev/null +++ b/src/system/app/mod.rs @@ -0,0 +1,23 @@ +use super::*; + +mod context; pub use context::*; +pub struct AppManager { + channel:Sender, +} + +impl AppManager { + +} + +impl Subsystem for AppManager { + fn start(_supervisor:Option>) -> Result, Error> + { + Err(Error::new()) + } +} + +impl From> for AppManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/audio/mod.rs b/src/system/audio/mod.rs index 1023c22..e66933a 100644 --- a/src/system/audio/mod.rs +++ b/src/system/audio/mod.rs @@ -14,3 +14,9 @@ impl Subsystem for AudioManager { Err(Error::new()) } } + +impl From> for AudioManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/control/mod.rs b/src/system/control/mod.rs index e91a754..1d0664a 100644 --- a/src/system/control/mod.rs +++ b/src/system/control/mod.rs @@ -14,3 +14,9 @@ impl Subsystem for ControlManager { Err(Error::new()) } } + +impl From> for ControlManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/input/mod.rs b/src/system/input/mod.rs index d3b3b29..02eae3b 100644 --- a/src/system/input/mod.rs +++ b/src/system/input/mod.rs @@ -29,3 +29,9 @@ impl Subsystem for InputManager { } } } + +impl From> for InputManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/mod.rs b/src/system/mod.rs index 0070e36..087f947 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -13,8 +13,11 @@ pub(crate) mod scene; pub(crate) use scene::*; pub(crate) mod network; pub(crate) use network::*; pub(crate) mod storage; pub(crate) use storage::*; pub(crate) mod api; pub(crate) use api::*; +pub(crate) mod api_control; pub(crate) use api_control::*; +pub(crate) mod api_device; pub(crate) use api_device::*; +pub(crate) mod app; pub(crate) use app::*; -pub(crate) trait Subsystem { +pub(crate) trait Subsystem : From> { fn start(supervisor:Option>) -> Result, Error>; fn shutdown() -> Result<(), Error> { Ok(()) } } @@ -23,7 +26,7 @@ pub(crate) trait Subsystem { pub enum System { Supervisor = 0, Window, - Render, + Video, Audio, Input, Control, @@ -31,5 +34,8 @@ pub enum System { Network, Storage, API, + APIDevice, + APIControl, + App, _MAX, } diff --git a/src/system/network/mod.rs b/src/system/network/mod.rs index 4c998c9..31acd3e 100644 --- a/src/system/network/mod.rs +++ b/src/system/network/mod.rs @@ -14,3 +14,9 @@ impl Subsystem for NetworkManager { Err(Error::new()) } } + +impl From> for NetworkManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/query.rs b/src/system/query.rs index 56bc5f2..171126e 100644 --- a/src/system/query.rs +++ b/src/system/query.rs @@ -15,6 +15,8 @@ impl Query { } pub enum QueryData { + Notify, + Supervisor(SupervisorQuery), API, Audio, diff --git a/src/system/scene/entity/camera.rs b/src/system/scene/entity/camera.rs new file mode 100644 index 0000000..7adf6d2 --- /dev/null +++ b/src/system/scene/entity/camera.rs @@ -0,0 +1,9 @@ +pub struct Camera { + position:glam::DVec3, + orientation:glam::Quat, + + fov:f64, + + transform:glam::DMat3, + itransform:glam::DMat3, +} diff --git a/src/system/scene/entity/mod.rs b/src/system/scene/entity/mod.rs new file mode 100644 index 0000000..38e0fc8 --- /dev/null +++ b/src/system/scene/entity/mod.rs @@ -0,0 +1 @@ +mod camera; pub use camera::Camera; diff --git a/src/system/scene/mod.rs b/src/system/scene/mod.rs index f458976..41ca8ce 100644 --- a/src/system/scene/mod.rs +++ b/src/system/scene/mod.rs @@ -1,6 +1,8 @@ use super::*; +mod entity; pub use entity::*; mod world; + pub struct SceneManager { channel:Sender, } @@ -15,3 +17,9 @@ impl Subsystem for SceneManager { Err(Error::new()) } } + +impl From> for SceneManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/storage/mod.rs b/src/system/storage/mod.rs index e37c67a..1fb2942 100644 --- a/src/system/storage/mod.rs +++ b/src/system/storage/mod.rs @@ -14,3 +14,9 @@ impl Subsystem for StorageManager { Err(Error::new()) } } + +impl From> for StorageManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/supervisor/mod.rs b/src/system/supervisor/mod.rs index e68dab6..1dd15d9 100644 --- a/src/system/supervisor/mod.rs +++ b/src/system/supervisor/mod.rs @@ -24,3 +24,9 @@ impl Subsystem for Supervisor { Ok(tx) } } + +impl From> for Supervisor { + fn from(channel:Sender) -> Self { + Self { channel } + } +} diff --git a/src/system/video/device/mod.rs b/src/system/video/device/mod.rs new file mode 100644 index 0000000..f745243 --- /dev/null +++ b/src/system/video/device/mod.rs @@ -0,0 +1,4 @@ +pub struct Device { + pub id:usize, + pub name:String, +} diff --git a/src/system/video/internal/mod.rs b/src/system/video/internal.rs similarity index 72% rename from src/system/video/internal/mod.rs rename to src/system/video/internal.rs index 60f0a5b..00a9d1e 100644 --- a/src/system/video/internal/mod.rs +++ b/src/system/video/internal.rs @@ -1,14 +1,26 @@ +use pool::Pool; + use crate::system::*; use super::vulkan::*; pub struct Internal { supervisor:Sender, + + devices:Pool<()>, + surfaces:Pool<()>, + swapchains:Pool<()>, + viewports:Pool<()>, } impl Internal { pub fn thread(supervisor:Sender, _tx:Sender, rx:Receiver) { let _sv = Internal { supervisor, + + devices:Pool::new(), + surfaces:Pool::new(), + swapchains:Pool::new(), + viewports:Pool::new(), }; // Initialize rendering system. diff --git a/src/system/video/mod.rs b/src/system/video/mod.rs index 09fdf91..e2b25d5 100644 --- a/src/system/video/mod.rs +++ b/src/system/video/mod.rs @@ -1,8 +1,9 @@ use super::*; +mod query; pub use query::*; +mod device; pub use device::Device; mod vulkan; use vulkan::Vulkan as Renderer; mod internal; use internal::Internal; -mod query; pub use query::VideoQuery; pub struct VideoManager { channel:Sender, @@ -30,3 +31,16 @@ impl Subsystem for VideoManager { } } +impl From> for VideoManager { + fn from(channel:Sender) -> Self { + Self { channel } + } +} + +/*** + +Context (physical device, window) + +Viewport + +***/ diff --git a/src/system/video/query.rs b/src/system/video/query.rs index 8785a85..021d73c 100644 --- a/src/system/video/query.rs +++ b/src/system/video/query.rs @@ -1,4 +1,29 @@ +use super::*; + pub enum VideoQuery { None, + GetDevices, + Devices { + devices:Vec, + }, + + CreateContext { + handle:WindowHandle, + }, + ContextCreated { + id:usize, + }, + + RefreshContext { + id:usize, + }, + + DestroyContext { + id:usize, + }, + + Render { + contexts:Vec, + }, } diff --git a/src/system/window/config.rs b/src/system/window/config.rs index 6833528..5ce4f75 100644 --- a/src/system/window/config.rs +++ b/src/system/window/config.rs @@ -1,13 +1,9 @@ pub struct WindowConfig { pub x:i32, pub y:i32, pub width:i32, pub height:i32, - pub visible:bool, + pub resize:bool, - pub caption:bool, - pub sysmenu:bool, - pub private:bool, - pub title:String, pub context:Option, } diff --git a/src/system/window/display.rs b/src/system/window/display.rs new file mode 100644 index 0000000..3198f7a --- /dev/null +++ b/src/system/window/display.rs @@ -0,0 +1,198 @@ +use windows::core::PCWSTR; +use windows::Win32::{ + Foundation::{ + BOOL, RECT, LPARAM, + GetLastError, + }, + Graphics::Gdi::{ + EnumDisplayMonitors, + GetMonitorInfoW, + EnumDisplayDevicesW, + DISPLAY_DEVICEW, + MONITORINFO, MONITORINFOEXW, + HMONITOR, HDC, + }, + UI::WindowsAndMessaging::MONITORINFOF_PRIMARY, + Devices::DeviceAndDriverInstallation::{ + SetupDiEnumDeviceInfo, + SetupDiGetClassDevsW, + SetupDiGetDeviceRegistryPropertyW, + SetupDiDestroyDeviceInfoList, + SetupDiOpenDevRegKey, + SPDRP_HARDWAREID, + DIGCF_PRESENT, + SP_DEVINFO_DATA, + GUID_DEVCLASS_MONITOR, + DICS_FLAG_GLOBAL, + DIREG_DEV, + DIGCF_DEVICEINTERFACE, + DIGCF_ALLCLASSES, + }, + Devices::Display::GUID_DEVINTERFACE_MONITOR, + System::Registry::{ + REG_SZ, + HKEY_LOCAL_MACHINE, + KEY_READ, + RegQueryValueExW, + }, +}; + +use pool::Pool; + +pub struct Display { + handle:HMONITOR, + name:String, + primary:bool, + + x:i32, y:i32, + width:i32, height:i32, + + wx:i32, wy:i32, + wwidth:i32, wheight:i32, +} + +pub struct DisplayManager { + displays:Vec, +} +impl DisplayManager { + pub fn new() -> Self + { + Self { + displays:Vec::new(), + } + } + + pub fn enumerate(&mut self) + { + self.displays.clear(); + unsafe { + EnumDisplayMonitors(None, None, Some(Self::enumerate_callback), LPARAM(&mut self.displays as *mut Vec as _)).ok().ok(); + } + } + + unsafe extern "system" fn enumerate_callback(hmonitor:HMONITOR, _hdc:HDC, _rect:*mut RECT, lparam:LPARAM) -> BOOL + { + let displays = lparam.0 as *mut Vec; + + let mut mi = MONITORINFOEXW { + monitorInfo:MONITORINFO { + cbSize: std::mem::size_of::() as u32, + ..Default::default() + }, + ..Default::default() + }; + + let mut dv = DISPLAY_DEVICEW { + cb: std::mem::size_of::() as u32, + ..Default::default() + }; + + let mut name = String::new(); + + if GetMonitorInfoW(hmonitor, &mut mi as *mut MONITORINFOEXW as _).as_bool() { + if EnumDisplayDevicesW(PCWSTR::from_raw(mi.szDevice.as_ptr()), 0, &mut dv as _, 1).as_bool() { + let raw_device_id = PCWSTR::from_raw(dv.DeviceID.as_ptr()).to_string().unwrap(); + let cleaned_device_id = raw_device_id + .trim_start_matches(r"\\?\") + .split("#{") + .collect::>()[0] + .replace('#', "\\") + .to_string(); + + match SetupDiGetClassDevsW( + None, + PCWSTR::from_raw(widestring::U16CString::from_str(cleaned_device_id).unwrap().as_ptr()), + None, + DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE, + ) { + Ok(hdevinfo) => { + if !hdevinfo.is_invalid() { + let mut devinfo_data = SP_DEVINFO_DATA { + cbSize:std::mem::size_of::() as u32, + ..Default::default() + }; + + let mut device_index = 0; + while SetupDiEnumDeviceInfo(hdevinfo, device_index, &mut devinfo_data).is_ok() { + const BUFFER_SIZE :usize = 256; + let mut buffer_size = BUFFER_SIZE as u32; + let mut buffer = [0u8; BUFFER_SIZE]; + let mut property_type = 0u32; + + match SetupDiGetDeviceRegistryPropertyW( + hdevinfo, + &devinfo_data, + SPDRP_HARDWAREID, + Some(&mut property_type), + Some(&mut buffer), + Some(&mut buffer_size as _) + ) { + Ok(_) => { + match SetupDiOpenDevRegKey( + hdevinfo, + &devinfo_data, + DICS_FLAG_GLOBAL.0, + 0, + DIREG_DEV, + KEY_READ.0, + ) { + Ok(hkey) => { + const KEY_BUFFER_SIZE :usize = 1024; + let mut key_buffer = [0u8; KEY_BUFFER_SIZE]; + let mut key_buffer_size = KEY_BUFFER_SIZE as u32; + + let result = RegQueryValueExW( + hkey, + PCWSTR::from_raw(widestring::U16CString::from_str("EDID\0").unwrap().as_ptr() as _), + None, + None, + Some(&mut key_buffer as _), + Some(&mut key_buffer_size), + ); + + if result.is_ok() { + const DESCRIPTOR_START :usize = 54; + for block in key_buffer[DESCRIPTOR_START..].chunks_exact(18) { + if block[3] == 0xFC { + name = String::from_utf8(block[5..18].to_vec()).unwrap_or_default().trim_end_matches(['\0', ' ', '\n', '\r']).to_string(); + } + } + } else { + println!("RegQueryValueExW: {}", result.0); + } + } + Err(e) => { println!("regkey: {}", e.message()); } + } + } + Err(e) => { println!("SetupDiOpenDevRegKey: {}", e.message()); } + } + + device_index += 1; + } + } + SetupDiDestroyDeviceInfoList(hdevinfo).ok(); + } + Err(e) => { println!("SetupDiGetClassDevsW: {} ; {}", e.message(), GetLastError().0); } + } + } + + (*displays).push(Display { + handle:hmonitor, + name, + primary:(mi.monitorInfo.dwFlags & MONITORINFOF_PRIMARY) != 0, + + x:mi.monitorInfo.rcMonitor.left, + y:mi.monitorInfo.rcMonitor.top, + width:mi.monitorInfo.rcMonitor.right - mi.monitorInfo.rcMonitor.left, + height:mi.monitorInfo.rcMonitor.bottom - mi.monitorInfo.rcMonitor.top, + + wx:mi.monitorInfo.rcWork.left, + wy:mi.monitorInfo.rcWork.top, + wwidth:mi.monitorInfo.rcWork.right - mi.monitorInfo.rcWork.left, + wheight:mi.monitorInfo.rcWork.bottom - mi.monitorInfo.rcWork.top, + }); + } + + BOOL(1) + } +} diff --git a/src/system/window/internal/mod.rs b/src/system/window/internal.rs similarity index 64% rename from src/system/window/internal/mod.rs rename to src/system/window/internal.rs index b8734c9..f89b77d 100644 --- a/src/system/window/internal/mod.rs +++ b/src/system/window/internal.rs @@ -45,10 +45,8 @@ use windows::{ WDA_MONITOR, CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, SW_SHOW, - WM_MOVE, WM_SIZE, - WM_INPUT, WM_DEVICECHANGE, WM_DISPLAYCHANGE, WM_NULL, - WS_OVERLAPPED, WS_POPUPWINDOW, + WS_POPUP, WS_OVERLAPPED, WS_POPUPWINDOW, WS_BORDER, WS_SIZEBOX, WS_CAPTION, WS_SYSMENU, WS_MINIMIZEBOX, WS_MAXIMIZEBOX, WS_VISIBLE, @@ -59,38 +57,49 @@ use windows::{ } }; use std::sync::RwLock; +use pool::Pool; -mod display; use display::DisplayManager; - -static mut WINPROC_SENDER :RwLock>> = RwLock::new(None); - -enum InternalQuery { - None, - Thread(u32), -} +use super::{ + display::DisplayManager, + winproc::{window_proc, WINPROC_SENDER}, +}; pub struct Internal { supervisor:Sender, + input:Option>, + video:Option>, + app:Option>, + display:DisplayManager, + windows:Pool, } impl Internal { pub fn thread(supervisor:Sender, tx:Sender, rx:Receiver) { - let _sv = Internal { + let mut sv = Internal { supervisor, + input:None, + video:None, + app:None, + display:DisplayManager::new(), + windows:Pool::new(), }; + let (system_sender, system_receiver) = crossbeam::channel::bounded::(16); + let (thread_sender, thread_receiver) = crossbeam::channel::bounded::(16); + if let Ok(channel) = unsafe {WINPROC_SENDER.get_mut()} { - *channel = Some(tx.clone()); + *channel = Some((tx.clone(), system_sender.clone())); } else { println!("error: failed to set window system sender."); } - let (system_sender, system_receiver) = crossbeam::channel::bounded::(16); - let (thread_sender, thread_receiver) = crossbeam::channel::bounded::(16); + // Enumerate monitors. + sv.display.enumerate(); + + // Prepare window handler thread. std::thread::spawn(move || { - let system_sender = system_sender; // Initialize window settings. let class_name = widestring::U16CString::from_str("donten-window-class").unwrap(); @@ -131,7 +140,7 @@ impl Internal { } } if unsafe {RegisterRawInputDevices(&rawinput_devices, std::mem::size_of::() as u32)}.is_err() { - println!("Failed to register input devices: {}", unsafe {GetLastError()}.to_hresult().message()); + println!("error: failed to register input devices: {}", unsafe {GetLastError()}.to_hresult().message()); } // Send thread id to system. @@ -140,7 +149,7 @@ impl Internal { // Process window events. let mut msg = MSG::default(); unsafe { - while GetMessageW(&mut msg, None, 0, 0).into() { + while GetMessageW(&mut msg, None, 0, 0).as_bool() { TranslateMessage(&msg).ok().ok(); DispatchMessageW(&msg); @@ -163,26 +172,25 @@ impl Internal { WindowQuery::Create { config, } => { - let dwexstyle = WS_EX_APPWINDOW; - let mut dwstyle = if config.caption { WS_OVERLAPPED } else { WS_POPUPWINDOW }; + let mut dwstyle = WS_POPUP | WS_BORDER | WS_VISIBLE; //if config.caption { WS_OVERLAPPED } else { WS_POPUPWINDOW }; - if config.sysmenu { + /*if config.sysmenu { dwstyle |= WS_SYSMENU | WS_MINIMIZEBOX; - } + }*/ if config.resize { - dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; + dwstyle |= WS_SIZEBOX; // | WS_MAXIMIZEBOX } - if config.visible { + /*if config.visible { dwstyle |= WS_VISIBLE; - } + }*/ match CreateWindowExW( dwexstyle, class_name, - PCWSTR(widestring::U16CString::from_str(config.title).unwrap().as_ptr()), + PCWSTR::null(), dwstyle, config.x, config.y, @@ -199,7 +207,11 @@ impl Internal { } // Return window information to manager. + if system_sender.send(InternalQuery::Create { + handle:hwnd.into(), + }).is_ok() { + } } Err(e) => { @@ -226,12 +238,99 @@ impl Internal { // Handle messages. while let Ok(msg) = rx.recv() { - match &msg.data { + match msg.data { + QueryData::Notify => { + while let Ok(msg) = system_receiver.try_recv() { + match msg { + + InternalQuery::Create { + handle, + } => { + sv.windows.add(handle.handle); + + if let Some(sc) = &sv.video { + sc.send(Query::new(Some(tx.clone()), QueryData::Video(VideoQuery::CreateContext { + handle:handle.clone(), + }))).ok(); + } + } + + InternalQuery::Close { + handle, + } => { + for id in sv.windows.list() { + if let Some(wnd) = sv.windows.get(id).cloned() { + if wnd == handle.handle { + sv.windows.remove(id).ok(); + break; + } + } + } + } + + InternalQuery::Input { + handle:_, + } => { + // Forward input data to system. + } + + InternalQuery::InputDeviceChange { + state:_, + handle:_, + } => { + println!("RECV DEVICECHANGE"); + + // Get new device information. + } + + InternalQuery::DeviceChange => { + println!("RECV DISPLAYCHANGE"); + + // Get new display information. + sv.display.enumerate(); + } + + _ => { } + } + } + } + + QueryData::Supervisor(query) => match query { + SupervisorQuery::Status { + system, + channel + } => match system { + System::Input => { + sv.input = channel; + } + + System::Video => { + sv.video = channel; + + // Prepare graphics context for each + } + + System::App => { + sv.app = channel; + } + + _ => { } + } + + SupervisorQuery::Stop { + system:_, + } => { + + } + + _ => { } + } + QueryData::Window(query) => match query { // Forward thread-required queries. WindowQuery::Create { .. } => { - if thread_sender.send(msg).is_ok() { + if thread_sender.send(Query::new(None, QueryData::Window(query))).is_ok() { // Dispatch window message to allow receiving of query. unsafe {PostThreadMessageW(thread_id, WM_NULL, WPARAM(0), LPARAM(0))}.ok(); } else { @@ -249,88 +348,3 @@ impl Internal { } } } - -unsafe extern "system" fn window_proc( - hwnd:HWND, - msg:u32, - wparam:WPARAM, - lparam:LPARAM, -) -> LRESULT { - if let Ok(sender) = WINPROC_SENDER.read() { - if let Some(_sender) = sender.as_ref() { - match msg { - WM_MOVE => { - - } - - WM_SIZE => { - - } - - WM_INPUT => { - //println!("INPUT"); - - let mut _rawinput_header = RAWINPUTHEADER::default(); - let header_size = std::mem::size_of::() as u32; - - let mut size = 0; - let result = unsafe {GetRawInputData( - HRAWINPUT(lparam.0 as _), - RID_INPUT, - None, - &mut size, - header_size, - )}; - - if result == 0 && size > 0 { - let mut buffer = vec![0u8; size as usize]; - - if unsafe {GetRawInputData( - HRAWINPUT(lparam.0 as _), - RID_INPUT, - Some(buffer.as_mut_ptr() as *mut _), - &mut size, - header_size, - )} > 0 { - let raw_input :&RAWINPUT = &*(buffer.as_ptr() as *const RAWINPUT); - - const TYPE_MOUSE :u32 = RIM_TYPEMOUSE.0; - const TYPE_KEYBOARD :u32 = RIM_TYPEKEYBOARD.0; - const TYPE_HID :u32 = RIM_TYPEHID.0; - match raw_input.header.dwType { - TYPE_MOUSE => { - let _data = unsafe {raw_input.data.mouse}; - //sender.send(0).ok(); - } - - TYPE_KEYBOARD => { - let _data = unsafe {raw_input.data.keyboard}; - } - - TYPE_HID => { - let _data = unsafe {raw_input.data.hid}; - } - - _ => { } - } - - } - } - - return LRESULT(0); - } - - WM_DEVICECHANGE => { - println!("DEVICECHANGE"); - } - - WM_DISPLAYCHANGE => { - println!("DISPLAYCHANGE"); - } - - _ => { } - } - } - } - DefWindowProcW(hwnd, msg, wparam, lparam) -} diff --git a/src/system/window/internal/display.rs b/src/system/window/internal/display.rs deleted file mode 100644 index 24050af..0000000 --- a/src/system/window/internal/display.rs +++ /dev/null @@ -1,37 +0,0 @@ -use windows::Win32::Graphics::Gdi::{ - EnumDisplayDevicesW, - DISPLAY_DEVICEW, -}; - -use pool::Pool; - -pub struct Display { - x:i32, y:i32, - width:i32, height:i32, -} - -pub struct DisplayManager { - displays:Pool, -} -impl DisplayManager { - pub fn new() -> Self - { - let mut this = Self { - displays:Pool::new(), - }; - - this.enumerate(); - this - } - - pub fn enumerate(&mut self) - { - let mut index = 0; - let mut device = DISPLAY_DEVICEW::default(); - while unsafe {EnumDisplayDevicesW(None, index, &mut device, 1)}.into() { - - - index += 1; - } - } -} diff --git a/src/system/window/layout.rs b/src/system/window/layout.rs index 44b52f0..03f8f65 100644 --- a/src/system/window/layout.rs +++ b/src/system/window/layout.rs @@ -1,12 +1,3 @@ -//use windows::Win32::Graphics::Gdi::EnumDisplayMonitors; - -pub struct MonitorInfo { - pub x:i32, - pub y:i32, - pub width:u32, - pub height:u32, -} - pub struct WindowLayout { pub x:i32, pub y:i32, @@ -16,10 +7,10 @@ pub struct WindowLayout { } pub struct Layout { - + name:String, + windows:Vec, } pub struct LayoutSystem { pub layouts:Vec, - pub monitors:Vec, } diff --git a/src/system/window/mod.rs b/src/system/window/mod.rs index af69d7f..6c5ac74 100644 --- a/src/system/window/mod.rs +++ b/src/system/window/mod.rs @@ -1,15 +1,18 @@ use super::*; -mod query; pub use query::WindowQuery; +mod windowhandle; pub use windowhandle::*; + +mod query; pub use query::*; mod config; pub use config::WindowConfig; mod layout; pub use layout::*; +mod winproc; +mod display; mod internal; use internal::Internal; pub struct WindowManager { channel:Sender, } - impl WindowManager { pub fn create(&self, config:WindowConfig) -> Result<(),()> { diff --git a/src/system/window/query.rs b/src/system/window/query.rs index 988c379..967fb88 100644 --- a/src/system/window/query.rs +++ b/src/system/window/query.rs @@ -1,4 +1,36 @@ -use super::WindowConfig; +use super::{WindowConfig, Layout, WindowHandle}; + +pub(crate) enum InternalQuery { + None, + Thread(u32), + + Create { + handle:WindowHandle, + }, + Close { + handle:WindowHandle, + }, + + Move { + handle:WindowHandle, + }, + Resize { + handle:WindowHandle, + width:i32, + height:i32, + }, + + + Input { + handle:WindowHandle, + }, + + DeviceChange, + InputDeviceChange { + state:bool, + handle:usize, + }, +} pub enum WindowQuery { None, @@ -41,6 +73,10 @@ pub enum WindowQuery { Configure { id:usize, }, - - +} + +pub enum LayoutQuery { + Build { + id:usize, + }, } diff --git a/src/system/window/windowhandle.rs b/src/system/window/windowhandle.rs new file mode 100644 index 0000000..b7b067b --- /dev/null +++ b/src/system/window/windowhandle.rs @@ -0,0 +1,13 @@ +pub type RawWindowHandle = windows::Win32::Foundation::HWND; + +#[derive(Clone, Copy)] +pub struct WindowHandle { + pub handle:RawWindowHandle, +} +unsafe impl Send for WindowHandle { } +impl From for WindowHandle { + fn from(value: RawWindowHandle) -> Self + { + Self { handle:value } + } +} diff --git a/src/system/window/winproc.rs b/src/system/window/winproc.rs new file mode 100644 index 0000000..8faabf5 --- /dev/null +++ b/src/system/window/winproc.rs @@ -0,0 +1,166 @@ +use crate::system::*; + +use std::sync::RwLock; +use windows::Win32::{ + Foundation::{ + HWND, + LPARAM, + LRESULT, + WPARAM, + }, + UI::{ + Input::{ + GetRawInputData, + HRAWINPUT, + RAWINPUT, + RAWINPUTDEVICE, + RAWINPUTHEADER, + RID_INPUT, + RIDEV_DEVNOTIFY, + RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, + }, + WindowsAndMessaging::{ + DefWindowProcW, + MSG, + WM_MOVE, WM_SIZE, WM_CLOSE, + WM_CAPTURECHANGED, + + WM_INPUT, WM_INPUT_DEVICE_CHANGE, + WM_DEVICECHANGE, WM_DISPLAYCHANGE, + WM_NULL, + }, + }, + System::Threading::GetCurrentThreadId, +}; + +use super::InternalQuery; + +pub static mut WINPROC_SENDER :RwLock, + crossbeam::channel::Sender +)>> = RwLock::new(None); + +pub unsafe extern "system" fn window_proc( + hwnd:HWND, + msg:u32, + wparam:WPARAM, + lparam:LPARAM, +) -> LRESULT { + if let Ok(sender) = WINPROC_SENDER.read() { + if let Some((notify, sender)) = sender.as_ref() { + match msg { + WM_MOVE => { + if sender.send(InternalQuery::Move { + handle:hwnd.into(), + }).is_ok() { + notify.send(Query::new(None, QueryData::Notify)).ok(); + } + } + + WM_SIZE => { + let width = lparam.0 as i32; + let height = (lparam.0 >> 32) as i32; + + if sender.send(InternalQuery::Resize { + handle:hwnd.into(), width, height, + }).is_ok() { + notify.send(Query::new(None, QueryData::Notify)).ok(); + } + } + + WM_CLOSE => { + if sender.send(InternalQuery::Close { + handle:hwnd.into(), + }).is_ok() { + notify.send(Query::new(None, QueryData::Notify)).ok(); + } + } + + + WM_CAPTURECHANGED => { + + } + + + WM_INPUT => { + let mut _rawinput_header = RAWINPUTHEADER::default(); + let header_size = std::mem::size_of::() as u32; + + let mut size = 0; + let result = unsafe {GetRawInputData( + HRAWINPUT(lparam.0 as _), + RID_INPUT, + None, + &mut size, + header_size, + )}; + + if result == 0 && size > 0 { + let mut buffer = vec![0u8; size as usize]; + + if unsafe {GetRawInputData( + HRAWINPUT(lparam.0 as _), + RID_INPUT, + Some(buffer.as_mut_ptr() as *mut _), + &mut size, + header_size, + )} > 0 { + let raw_input :&RAWINPUT = &*(buffer.as_ptr() as *const RAWINPUT); + + let resp = InternalQuery::Input { + handle:hwnd.into(), + }; + + const TYPE_MOUSE :u32 = RIM_TYPEMOUSE.0; + const TYPE_KEYBOARD :u32 = RIM_TYPEKEYBOARD.0; + const TYPE_HID :u32 = RIM_TYPEHID.0; + match raw_input.header.dwType { + TYPE_MOUSE => { + let _data = unsafe {raw_input.data.mouse}; + //sender.send(0).ok(); + } + + TYPE_KEYBOARD => { + let _data = unsafe {raw_input.data.keyboard}; + } + + TYPE_HID => { + let _data = unsafe {raw_input.data.hid}; + } + + _ => { } + } + + if sender.send(resp).is_ok() { + notify.send(Query::new(None, QueryData::Notify)).ok(); + } + } + } + + return LRESULT(0); + } + + WM_INPUT_DEVICE_CHANGE => { + let state = wparam.0 == 1; + let handle = lparam.0 as usize; + + if sender.send(InternalQuery::InputDeviceChange { + state, + handle, + }).is_ok() { + notify.send(Query::new(None, QueryData::Notify)).ok(); + } + } + + WM_DEVICECHANGE | WM_DISPLAYCHANGE => { + if sender.send(InternalQuery::DeviceChange).is_ok() { + notify.send(Query::new(None, QueryData::Notify)).ok(); + } + } + + _ => { } + } + } + } + DefWindowProcW(hwnd, msg, wparam, lparam) +}