Modify window handling.
This commit is contained in:
parent
cde7b3560f
commit
9a36e1c4f8
@ -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"
|
||||||
|
|
||||||
|
30
doc/design/network/api_control.md
Normal file
30
doc/design/network/api_control.md
Normal 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
|
4
doc/design/network/srv.md
Normal file
4
doc/design/network/srv.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# SRV Records
|
||||||
|
|
||||||
|
- _donten._tcp.example.com
|
||||||
|
- _donten._udp.example.com
|
@ -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.
|
||||||
}
|
}
|
||||||
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
74
src/system/api_control/mod.rs
Normal file
74
src/system/api_control/mod.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
0
src/system/api_device/mod.rs
Normal file
0
src/system/api_device/mod.rs
Normal file
11
src/system/app/context/launcher.rs
Normal file
11
src/system/app/context/launcher.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct Launcher {
|
||||||
|
|
||||||
|
}
|
||||||
|
impl Launcher {
|
||||||
|
|
||||||
|
}
|
||||||
|
impl Context for Launcher {
|
||||||
|
|
||||||
|
}
|
5
src/system/app/context/mod.rs
Normal file
5
src/system/app/context/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub trait Context {
|
||||||
|
fn draw() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
mod launcher; use launcher::Launcher;
|
23
src/system/app/mod.rs
Normal file
23
src/system/app/mod.rs
Normal 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 }
|
||||||
|
}
|
||||||
|
}
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -29,3 +29,9 @@ impl Subsystem for InputManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Sender<Query>> for InputManager {
|
||||||
|
fn from(channel:Sender<Query>) -> Self {
|
||||||
|
Self { channel }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,8 @@ impl Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum QueryData {
|
pub enum QueryData {
|
||||||
|
Notify,
|
||||||
|
|
||||||
Supervisor(SupervisorQuery),
|
Supervisor(SupervisorQuery),
|
||||||
API,
|
API,
|
||||||
Audio,
|
Audio,
|
||||||
|
9
src/system/scene/entity/camera.rs
Normal file
9
src/system/scene/entity/camera.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub struct Camera {
|
||||||
|
position:glam::DVec3,
|
||||||
|
orientation:glam::Quat,
|
||||||
|
|
||||||
|
fov:f64,
|
||||||
|
|
||||||
|
transform:glam::DMat3,
|
||||||
|
itransform:glam::DMat3,
|
||||||
|
}
|
1
src/system/scene/entity/mod.rs
Normal file
1
src/system/scene/entity/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
mod camera; pub use camera::Camera;
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4
src/system/video/device/mod.rs
Normal file
4
src/system/video/device/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub struct Device {
|
||||||
|
pub id:usize,
|
||||||
|
pub name:String,
|
||||||
|
}
|
@ -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.
|
@ -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
|
||||||
|
|
||||||
|
***/
|
||||||
|
@ -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>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -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 resize:bool,
|
||||||
pub caption:bool,
|
|
||||||
pub sysmenu:bool,
|
|
||||||
|
|
||||||
pub private:bool,
|
pub private:bool,
|
||||||
|
|
||||||
pub title:String,
|
|
||||||
pub context:Option<usize>,
|
pub context:Option<usize>,
|
||||||
}
|
}
|
||||||
|
198
src/system/window/display.rs
Normal file
198
src/system/window/display.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -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,7 +207,11 @@ 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) => {
|
||||||
@ -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)
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>,
|
|
||||||
}
|
}
|
||||||
|
@ -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<(),()>
|
||||||
{
|
{
|
||||||
|
@ -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,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
13
src/system/window/windowhandle.rs
Normal file
13
src/system/window/windowhandle.rs
Normal 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 }
|
||||||
|
}
|
||||||
|
}
|
166
src/system/window/winproc.rs
Normal file
166
src/system/window/winproc.rs
Normal 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)
|
||||||
|
}
|
Reference in New Issue
Block a user