Modify window handling.

This commit is contained in:
yukirij 2024-12-12 01:07:40 -08:00
parent cde7b3560f
commit 9a36e1c4f8
34 changed files with 833 additions and 177 deletions

View File

@ -10,6 +10,9 @@ crossbeam = "0.8.4"
vulkano = "0.34.1" vulkano = "0.34.1"
glam = "0.29.2" glam = "0.29.2"
egui = "0.29.1"
cpal = "0.15.3"
pool = { git = "https://git.tsukiyo.org/Utility/pool" } pool = { git = "https://git.tsukiyo.org/Utility/pool" }
@ -19,7 +22,10 @@ windows = { version = "0.58.0", features = [
"Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging",
"Win32_Graphics_Gdi", "Win32_Graphics_Gdi",
"Win32_UI_Input", "Win32_UI_Input",
"Win32_System_Registry",
"Win32_System_Threading", "Win32_System_Threading",
"Win32_Devices_DeviceAndDriverInstallation",
"Win32_Devices_Display",
] } ] }
widestring = "1.1.0" widestring = "1.1.0"

View File

@ -0,0 +1,30 @@
# Control API
## Packet
```
<Id:4B> <Secret:12B> <Data:496B>
```
### Encryption
## Commnad
Each packet may provide up to 62 commands.
```
<OpCode:2b> <Code:14b> <Channel:16b> <Value:32b>
```
### OpCode
- (0) Info
- (1) Get
- (2) Set
- (3) Add
### Code
### Channel
### Value

View File

@ -0,0 +1,4 @@
# SRV Records
- _donten._tcp.example.com
- _donten._udp.example.com

View File

@ -18,12 +18,12 @@ fn main()
sys_win.create(donten::WindowConfig { sys_win.create(donten::WindowConfig {
x: CW_USEDEFAULT, y: CW_USEDEFAULT, x: CW_USEDEFAULT, y: CW_USEDEFAULT,
width: 640, height: 480, width: 640, height: 480,
visible: true, resize: false,
resize: false, caption: true, sysmenu: false,
private: false, private: false,
title: "Hello".to_string(),
context: None, context: None,
}).ok(); }).ok();
std::thread::park(); std::thread::park();
// Handle command queries.
} }

View File

@ -14,3 +14,9 @@ impl Subsystem for APIManager {
Err(Error::new()) Err(Error::new())
} }
} }
impl From<Sender<Query>> for APIManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -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<Vec<Command>,()>
{
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(())
}
}
}

View File

View File

@ -0,0 +1,11 @@
use super::*;
pub struct Launcher {
}
impl Launcher {
}
impl Context for Launcher {
}

View File

@ -0,0 +1,5 @@
pub trait Context {
fn draw() { }
}
mod launcher; use launcher::Launcher;

23
src/system/app/mod.rs Normal file
View File

@ -0,0 +1,23 @@
use super::*;
mod context; pub use context::*;
pub struct AppManager {
channel:Sender<Query>,
}
impl AppManager {
}
impl Subsystem for AppManager {
fn start(_supervisor:Option<Sender<Query>>) -> Result<Sender<Query>, Error>
{
Err(Error::new())
}
}
impl From<Sender<Query>> for AppManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -14,3 +14,9 @@ impl Subsystem for AudioManager {
Err(Error::new()) Err(Error::new())
} }
} }
impl From<Sender<Query>> for AudioManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -14,3 +14,9 @@ impl Subsystem for ControlManager {
Err(Error::new()) Err(Error::new())
} }
} }
impl From<Sender<Query>> for ControlManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -29,3 +29,9 @@ impl Subsystem for InputManager {
} }
} }
} }
impl From<Sender<Query>> for InputManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -13,8 +13,11 @@ pub(crate) mod scene; pub(crate) use scene::*;
pub(crate) mod network; pub(crate) use network::*; pub(crate) mod network; pub(crate) use network::*;
pub(crate) mod storage; pub(crate) use storage::*; pub(crate) mod storage; pub(crate) use storage::*;
pub(crate) mod api; pub(crate) use api::*; 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<Sender<Query>> {
fn start(supervisor:Option<Sender<Query>>) -> Result<Sender<Query>, Error>; fn start(supervisor:Option<Sender<Query>>) -> Result<Sender<Query>, Error>;
fn shutdown() -> Result<(), Error> { Ok(()) } fn shutdown() -> Result<(), Error> { Ok(()) }
} }
@ -23,7 +26,7 @@ pub(crate) trait Subsystem {
pub enum System { pub enum System {
Supervisor = 0, Supervisor = 0,
Window, Window,
Render, Video,
Audio, Audio,
Input, Input,
Control, Control,
@ -31,5 +34,8 @@ pub enum System {
Network, Network,
Storage, Storage,
API, API,
APIDevice,
APIControl,
App,
_MAX, _MAX,
} }

View File

@ -14,3 +14,9 @@ impl Subsystem for NetworkManager {
Err(Error::new()) Err(Error::new())
} }
} }
impl From<Sender<Query>> for NetworkManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -15,6 +15,8 @@ impl Query {
} }
pub enum QueryData { pub enum QueryData {
Notify,
Supervisor(SupervisorQuery), Supervisor(SupervisorQuery),
API, API,
Audio, Audio,

View File

@ -0,0 +1,9 @@
pub struct Camera {
position:glam::DVec3,
orientation:glam::Quat,
fov:f64,
transform:glam::DMat3,
itransform:glam::DMat3,
}

View File

@ -0,0 +1 @@
mod camera; pub use camera::Camera;

View File

@ -1,6 +1,8 @@
use super::*; use super::*;
mod entity; pub use entity::*;
mod world; mod world;
pub struct SceneManager { pub struct SceneManager {
channel:Sender<Query>, channel:Sender<Query>,
} }
@ -15,3 +17,9 @@ impl Subsystem for SceneManager {
Err(Error::new()) Err(Error::new())
} }
} }
impl From<Sender<Query>> for SceneManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -14,3 +14,9 @@ impl Subsystem for StorageManager {
Err(Error::new()) Err(Error::new())
} }
} }
impl From<Sender<Query>> for StorageManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -24,3 +24,9 @@ impl Subsystem for Supervisor {
Ok(tx) Ok(tx)
} }
} }
impl From<Sender<Query>> for Supervisor {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}

View File

@ -0,0 +1,4 @@
pub struct Device {
pub id:usize,
pub name:String,
}

View File

@ -1,14 +1,26 @@
use pool::Pool;
use crate::system::*; use crate::system::*;
use super::vulkan::*; use super::vulkan::*;
pub struct Internal { pub struct Internal {
supervisor:Sender<Query>, supervisor:Sender<Query>,
devices:Pool<()>,
surfaces:Pool<()>,
swapchains:Pool<()>,
viewports:Pool<()>,
} }
impl Internal { impl Internal {
pub fn thread(supervisor:Sender<Query>, _tx:Sender<Query>, rx:Receiver<Query>) pub fn thread(supervisor:Sender<Query>, _tx:Sender<Query>, rx:Receiver<Query>)
{ {
let _sv = Internal { let _sv = Internal {
supervisor, supervisor,
devices:Pool::new(),
surfaces:Pool::new(),
swapchains:Pool::new(),
viewports:Pool::new(),
}; };
// Initialize rendering system. // Initialize rendering system.

View File

@ -1,8 +1,9 @@
use super::*; use super::*;
mod query; pub use query::*;
mod device; pub use device::Device;
mod vulkan; use vulkan::Vulkan as Renderer; mod vulkan; use vulkan::Vulkan as Renderer;
mod internal; use internal::Internal; mod internal; use internal::Internal;
mod query; pub use query::VideoQuery;
pub struct VideoManager { pub struct VideoManager {
channel:Sender<Query>, channel:Sender<Query>,
@ -30,3 +31,16 @@ impl Subsystem for VideoManager {
} }
} }
impl From<Sender<Query>> for VideoManager {
fn from(channel:Sender<Query>) -> Self {
Self { channel }
}
}
/***
Context (physical device, window)
Viewport
***/

View File

@ -1,4 +1,29 @@
use super::*;
pub enum VideoQuery { pub enum VideoQuery {
None, None,
GetDevices,
Devices {
devices:Vec<Device>,
},
CreateContext {
handle:WindowHandle,
},
ContextCreated {
id:usize,
},
RefreshContext {
id:usize,
},
DestroyContext {
id:usize,
},
Render {
contexts:Vec<usize>,
},
} }

View File

@ -1,13 +1,9 @@
pub struct WindowConfig { pub struct WindowConfig {
pub x:i32, pub y:i32, pub x:i32, pub y:i32,
pub width:i32, pub height:i32, pub width:i32, pub height:i32,
pub visible:bool,
pub resize:bool,
pub caption:bool,
pub sysmenu:bool,
pub resize:bool,
pub private:bool, pub private:bool,
pub title:String,
pub context:Option<usize>, pub context:Option<usize>,
} }

View File

@ -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<Display>,
}
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<Display> 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<Display>;
let mut mi = MONITORINFOEXW {
monitorInfo:MONITORINFO {
cbSize: std::mem::size_of::<MONITORINFOEXW>() as u32,
..Default::default()
},
..Default::default()
};
let mut dv = DISPLAY_DEVICEW {
cb: std::mem::size_of::<DISPLAY_DEVICEW>() 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::<Vec<_>>()[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::<SP_DEVINFO_DATA>() 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)
}
}

View File

@ -45,10 +45,8 @@ use windows::{
WDA_MONITOR, WDA_MONITOR,
CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT,
SW_SHOW, SW_SHOW,
WM_MOVE, WM_SIZE,
WM_INPUT, WM_DEVICECHANGE, WM_DISPLAYCHANGE,
WM_NULL, WM_NULL,
WS_OVERLAPPED, WS_POPUPWINDOW, WS_POPUP, WS_OVERLAPPED, WS_POPUPWINDOW,
WS_BORDER, WS_SIZEBOX, WS_CAPTION, WS_BORDER, WS_SIZEBOX, WS_CAPTION,
WS_SYSMENU, WS_MINIMIZEBOX, WS_MAXIMIZEBOX, WS_SYSMENU, WS_MINIMIZEBOX, WS_MAXIMIZEBOX,
WS_VISIBLE, WS_VISIBLE,
@ -59,38 +57,49 @@ use windows::{
} }
}; };
use std::sync::RwLock; use std::sync::RwLock;
use pool::Pool;
mod display; use display::DisplayManager; use super::{
display::DisplayManager,
static mut WINPROC_SENDER :RwLock<Option<crossbeam::channel::Sender<Query>>> = RwLock::new(None); winproc::{window_proc, WINPROC_SENDER},
};
enum InternalQuery {
None,
Thread(u32),
}
pub struct Internal { pub struct Internal {
supervisor:Sender<Query>, supervisor:Sender<Query>,
input:Option<Sender<Query>>,
video:Option<Sender<Query>>,
app:Option<Sender<Query>>,
display:DisplayManager, display:DisplayManager,
windows:Pool<HWND>,
} }
impl Internal { impl Internal {
pub fn thread(supervisor:Sender<Query>, tx:Sender<Query>, rx:Receiver<Query>) pub fn thread(supervisor:Sender<Query>, tx:Sender<Query>, rx:Receiver<Query>)
{ {
let _sv = Internal { let mut sv = Internal {
supervisor, supervisor,
input:None,
video:None,
app:None,
display:DisplayManager::new(), display:DisplayManager::new(),
windows:Pool::new(),
}; };
let (system_sender, system_receiver) = crossbeam::channel::bounded::<InternalQuery>(16);
let (thread_sender, thread_receiver) = crossbeam::channel::bounded::<Query>(16);
if let Ok(channel) = unsafe {WINPROC_SENDER.get_mut()} { if let Ok(channel) = unsafe {WINPROC_SENDER.get_mut()} {
*channel = Some(tx.clone()); *channel = Some((tx.clone(), system_sender.clone()));
} else { } else {
println!("error: failed to set window system sender."); println!("error: failed to set window system sender.");
} }
let (system_sender, system_receiver) = crossbeam::channel::bounded::<InternalQuery>(16); // Enumerate monitors.
let (thread_sender, thread_receiver) = crossbeam::channel::bounded::<Query>(16); sv.display.enumerate();
// Prepare window handler thread.
std::thread::spawn(move || { std::thread::spawn(move || {
let system_sender = system_sender;
// Initialize window settings. // Initialize window settings.
let class_name = widestring::U16CString::from_str("donten-window-class").unwrap(); 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::<RAWINPUTDEVICE>() as u32)}.is_err() { if unsafe {RegisterRawInputDevices(&rawinput_devices, std::mem::size_of::<RAWINPUTDEVICE>() 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. // Send thread id to system.
@ -140,7 +149,7 @@ impl Internal {
// Process window events. // Process window events.
let mut msg = MSG::default(); let mut msg = MSG::default();
unsafe { unsafe {
while GetMessageW(&mut msg, None, 0, 0).into() { while GetMessageW(&mut msg, None, 0, 0).as_bool() {
TranslateMessage(&msg).ok().ok(); TranslateMessage(&msg).ok().ok();
DispatchMessageW(&msg); DispatchMessageW(&msg);
@ -163,26 +172,25 @@ impl Internal {
WindowQuery::Create { WindowQuery::Create {
config, config,
} => { } => {
let dwexstyle = WS_EX_APPWINDOW; 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; dwstyle |= WS_SYSMENU | WS_MINIMIZEBOX;
} }*/
if config.resize { if config.resize {
dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; dwstyle |= WS_SIZEBOX; // | WS_MAXIMIZEBOX
} }
if config.visible { /*if config.visible {
dwstyle |= WS_VISIBLE; dwstyle |= WS_VISIBLE;
} }*/
match CreateWindowExW( match CreateWindowExW(
dwexstyle, dwexstyle,
class_name, class_name,
PCWSTR(widestring::U16CString::from_str(config.title).unwrap().as_ptr()), PCWSTR::null(),
dwstyle, dwstyle,
config.x, config.x,
config.y, config.y,
@ -199,8 +207,12 @@ impl Internal {
} }
// Return window information to manager. // Return window information to manager.
if system_sender.send(InternalQuery::Create {
handle:hwnd.into(),
}).is_ok() {
} }
}
Err(e) => { Err(e) => {
println!("error: {}", e.to_string()); println!("error: {}", e.to_string());
@ -226,12 +238,99 @@ impl Internal {
// Handle messages. // Handle messages.
while let Ok(msg) = rx.recv() { 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 { QueryData::Window(query) => match query {
// Forward thread-required queries. // Forward thread-required queries.
WindowQuery::Create { .. } => { 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. // Dispatch window message to allow receiving of query.
unsafe {PostThreadMessageW(thread_id, WM_NULL, WPARAM(0), LPARAM(0))}.ok(); unsafe {PostThreadMessageW(thread_id, WM_NULL, WPARAM(0), LPARAM(0))}.ok();
} else { } 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::<RAWINPUTHEADER>() 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)
}

View File

@ -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<Display>,
}
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;
}
}
}

View File

@ -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 struct WindowLayout {
pub x:i32, pub x:i32,
pub y:i32, pub y:i32,
@ -16,10 +7,10 @@ pub struct WindowLayout {
} }
pub struct Layout { pub struct Layout {
name:String,
windows:Vec<WindowLayout>,
} }
pub struct LayoutSystem { pub struct LayoutSystem {
pub layouts:Vec<Layout>, pub layouts:Vec<Layout>,
pub monitors:Vec<MonitorInfo>,
} }

View File

@ -1,15 +1,18 @@
use super::*; 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 config; pub use config::WindowConfig;
mod layout; pub use layout::*; mod layout; pub use layout::*;
mod winproc;
mod display;
mod internal; use internal::Internal; mod internal; use internal::Internal;
pub struct WindowManager { pub struct WindowManager {
channel:Sender<Query>, channel:Sender<Query>,
} }
impl WindowManager { impl WindowManager {
pub fn create(&self, config:WindowConfig) -> Result<(),()> pub fn create(&self, config:WindowConfig) -> Result<(),()>
{ {

View File

@ -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 { pub enum WindowQuery {
None, None,
@ -41,6 +73,10 @@ pub enum WindowQuery {
Configure { Configure {
id:usize, id:usize,
}, },
}
pub enum LayoutQuery {
Build {
id:usize,
},
} }

View File

@ -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<RawWindowHandle> for WindowHandle {
fn from(value: RawWindowHandle) -> Self
{
Self { handle:value }
}
}

View File

@ -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<Option<(
crossbeam::channel::Sender<Query>,
crossbeam::channel::Sender<InternalQuery>
)>> = 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::<RAWINPUTHEADER>() 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)
}