better support for win7
This commit is contained in:
parent
7630713534
commit
f760e56f79
@ -62,13 +62,23 @@ pub struct Display(dxgi::Display);
|
|||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub fn primary() -> io::Result<Display> {
|
pub fn primary() -> io::Result<Display> {
|
||||||
match dxgi::Displays::new()?.next() {
|
// not implemented yet
|
||||||
Some(inner) => Ok(Display(inner)),
|
Err(NotFound.into())
|
||||||
None => Err(NotFound.into()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all() -> io::Result<Vec<Display>> {
|
pub fn all() -> io::Result<Vec<Display>> {
|
||||||
|
let tmp = Self::all_().unwrap_or(Default::default());
|
||||||
|
if tmp.is_empty() {
|
||||||
|
println!("Display got from gdi");
|
||||||
|
return Ok(dxgi::Displays::get_from_gdi()
|
||||||
|
.drain(..)
|
||||||
|
.map(Display)
|
||||||
|
.collect::<Vec<_>>());
|
||||||
|
}
|
||||||
|
Ok(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_() -> io::Result<Vec<Display>> {
|
||||||
Ok(dxgi::Displays::new()?.map(Display).collect::<Vec<_>>())
|
Ok(dxgi::Displays::new()?.map(Display).collect::<Vec<_>>())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,13 +102,12 @@ impl Display {
|
|||||||
self.0.is_online()
|
self.0.is_online()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn origin(&self) -> (usize, usize) {
|
pub fn origin(&self) -> (i32, i32) {
|
||||||
let o = self.0.origin();
|
self.0.origin()
|
||||||
(o.0 as usize, o.1 as usize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to-do: not found primary display api for dxgi
|
|
||||||
pub fn is_primary(&self) -> bool {
|
pub fn is_primary(&self) -> bool {
|
||||||
self.name() == Self::primary().unwrap().name()
|
// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodea
|
||||||
|
self.origin() == (0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,9 +114,9 @@ impl Display {
|
|||||||
self.0.is_online()
|
self.0.is_online()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn origin(&self) -> (usize, usize) {
|
pub fn origin(&self) -> (i32, i32) {
|
||||||
let o = self.0.bounds().origin;
|
let o = self.0.bounds().origin;
|
||||||
(o.x as usize, o.y as usize)
|
(o.x as _, o.y as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_primary(&self) -> bool {
|
pub fn is_primary(&self) -> bool {
|
||||||
|
@ -68,7 +68,7 @@ impl Display {
|
|||||||
self.0.rect().h as usize
|
self.0.rect().h as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn origin(&self) -> (usize, usize) {
|
pub fn origin(&self) -> (i32, i32) {
|
||||||
let r = self.0.rect();
|
let r = self.0.rect();
|
||||||
(r.x as _, r.y as _)
|
(r.x as _, r.y as _)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use winapi::{
|
|||||||
BITMAPINFO,
|
BITMAPINFO,
|
||||||
BITMAPINFOHEADER,
|
BITMAPINFOHEADER,
|
||||||
BI_RGB,
|
BI_RGB,
|
||||||
|
CAPTUREBLT,
|
||||||
DIB_RGB_COLORS, //CAPTUREBLT,
|
DIB_RGB_COLORS, //CAPTUREBLT,
|
||||||
HGDI_ERROR,
|
HGDI_ERROR,
|
||||||
RGBQUAD,
|
RGBQUAD,
|
||||||
@ -97,7 +98,7 @@ impl CapturerGDI {
|
|||||||
self.screen_dc,
|
self.screen_dc,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
SRCCOPY, // | CAPTUREBLT, // CAPTUREBLT enable layered window but also make cursor blinking
|
SRCCOPY | CAPTUREBLT, // CAPTUREBLT enable layered window but also make cursor blinking
|
||||||
);
|
);
|
||||||
if res == 0 {
|
if res == 0 {
|
||||||
return Err("Failed to copy screen to Windows buffer".into());
|
return Err("Failed to copy screen to Windows buffer".into());
|
||||||
|
@ -12,7 +12,7 @@ use winapi::{
|
|||||||
// shared::dxgiformat::{DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_420_OPAQUE},
|
// shared::dxgiformat::{DXGI_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_420_OPAQUE},
|
||||||
shared::dxgi1_2::{IDXGIOutput1, IID_IDXGIOutput1},
|
shared::dxgi1_2::{IDXGIOutput1, IID_IDXGIOutput1},
|
||||||
shared::dxgitype::DXGI_MODE_ROTATION,
|
shared::dxgitype::DXGI_MODE_ROTATION,
|
||||||
shared::minwindef::{TRUE, UINT},
|
shared::minwindef::{DWORD, FALSE, TRUE, UINT},
|
||||||
shared::ntdef::LONG,
|
shared::ntdef::LONG,
|
||||||
shared::windef::HMONITOR,
|
shared::windef::HMONITOR,
|
||||||
shared::winerror::{
|
shared::winerror::{
|
||||||
@ -25,7 +25,9 @@ use winapi::{
|
|||||||
D3D11_CPU_ACCESS_READ, D3D11_SDK_VERSION, D3D11_USAGE_STAGING,
|
D3D11_CPU_ACCESS_READ, D3D11_SDK_VERSION, D3D11_USAGE_STAGING,
|
||||||
},
|
},
|
||||||
um::d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
um::d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
um::wingdi::*,
|
||||||
um::winnt::HRESULT,
|
um::winnt::HRESULT,
|
||||||
|
um::winuser::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Split up into files.
|
//TODO: Split up into files.
|
||||||
@ -55,20 +57,24 @@ impl Capturer {
|
|||||||
let mut desc = unsafe { mem::MaybeUninit::uninit().assume_init() };
|
let mut desc = unsafe { mem::MaybeUninit::uninit().assume_init() };
|
||||||
let mut gdi_capturer = None;
|
let mut gdi_capturer = None;
|
||||||
|
|
||||||
let mut res = wrap_hresult(unsafe {
|
let mut res = if display.gdi {
|
||||||
D3D11CreateDevice(
|
wrap_hresult(1)
|
||||||
display.adapter as *mut _,
|
} else {
|
||||||
D3D_DRIVER_TYPE_UNKNOWN,
|
wrap_hresult(unsafe {
|
||||||
ptr::null_mut(), // No software rasterizer.
|
D3D11CreateDevice(
|
||||||
0, // No device flags.
|
display.adapter as *mut _,
|
||||||
ptr::null_mut(), // Feature levels.
|
D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
0, // Feature levels' length.
|
ptr::null_mut(), // No software rasterizer.
|
||||||
D3D11_SDK_VERSION,
|
0, // No device flags.
|
||||||
&mut device,
|
ptr::null_mut(), // Feature levels.
|
||||||
ptr::null_mut(),
|
0, // Feature levels' length.
|
||||||
&mut context,
|
D3D11_SDK_VERSION,
|
||||||
)
|
&mut device,
|
||||||
});
|
ptr::null_mut(),
|
||||||
|
&mut context,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
gdi_capturer = display.create_gdi();
|
gdi_capturer = display.create_gdi();
|
||||||
@ -346,6 +352,56 @@ impl Displays {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_from_gdi() -> Vec<Display> {
|
||||||
|
let mut all = Vec::new();
|
||||||
|
let mut i: DWORD = 0;
|
||||||
|
loop {
|
||||||
|
let mut d: DISPLAY_DEVICEW = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
|
||||||
|
d.cb = std::mem::size_of::<DISPLAY_DEVICEW>() as _;
|
||||||
|
let ok = unsafe { EnumDisplayDevicesW(std::ptr::null(), i, &mut d as _, 0) };
|
||||||
|
if ok == FALSE {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
if 0 == (d.StateFlags & DISPLAY_DEVICE_ACTIVE)
|
||||||
|
|| (d.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) > 0
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// let is_primary = (d.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) > 0;
|
||||||
|
let mut disp = Display {
|
||||||
|
inner: std::ptr::null_mut(),
|
||||||
|
adapter: std::ptr::null_mut(),
|
||||||
|
desc: unsafe { std::mem::zeroed() },
|
||||||
|
gdi: true,
|
||||||
|
};
|
||||||
|
disp.desc.DeviceName = d.DeviceName;
|
||||||
|
let mut m: DEVMODEW = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
|
||||||
|
m.dmSize = std::mem::size_of::<DEVMODEW>() as _;
|
||||||
|
m.dmDriverExtra = 0;
|
||||||
|
let ok = unsafe {
|
||||||
|
EnumDisplaySettingsExW(
|
||||||
|
disp.desc.DeviceName.as_ptr(),
|
||||||
|
ENUM_CURRENT_SETTINGS,
|
||||||
|
&mut m as _,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if ok == FALSE {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
disp.desc.DesktopCoordinates.left = unsafe { m.u1.s2().dmPosition.x };
|
||||||
|
disp.desc.DesktopCoordinates.top = unsafe { m.u1.s2().dmPosition.y };
|
||||||
|
disp.desc.DesktopCoordinates.right =
|
||||||
|
disp.desc.DesktopCoordinates.left + m.dmPelsWidth as i32;
|
||||||
|
disp.desc.DesktopCoordinates.bottom =
|
||||||
|
disp.desc.DesktopCoordinates.top + m.dmPelsHeight as i32;
|
||||||
|
disp.desc.AttachedToDesktop = 1;
|
||||||
|
all.push(disp);
|
||||||
|
}
|
||||||
|
all
|
||||||
|
}
|
||||||
|
|
||||||
// No Adapter => Some(None)
|
// No Adapter => Some(None)
|
||||||
// Non-Empty Adapter => Some(Some(OUTPUT))
|
// Non-Empty Adapter => Some(Some(OUTPUT))
|
||||||
// End of Adapter => None
|
// End of Adapter => None
|
||||||
@ -414,6 +470,7 @@ impl Displays {
|
|||||||
inner,
|
inner,
|
||||||
adapter: self.adapter,
|
adapter: self.adapter,
|
||||||
desc,
|
desc,
|
||||||
|
gdi: false,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -460,8 +517,11 @@ pub struct Display {
|
|||||||
inner: *mut IDXGIOutput1,
|
inner: *mut IDXGIOutput1,
|
||||||
adapter: *mut IDXGIAdapter1,
|
adapter: *mut IDXGIAdapter1,
|
||||||
desc: DXGI_OUTPUT_DESC,
|
desc: DXGI_OUTPUT_DESC,
|
||||||
|
gdi: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/dchapyshev/aspia/blob/59233c5d01a4d03ed6de19b03ce77d61a6facf79/source/base/desktop/win/screen_capture_utils.cc
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub fn width(&self) -> LONG {
|
pub fn width(&self) -> LONG {
|
||||||
self.desc.DesktopCoordinates.right - self.desc.DesktopCoordinates.left
|
self.desc.DesktopCoordinates.right - self.desc.DesktopCoordinates.left
|
||||||
@ -511,6 +571,9 @@ impl Display {
|
|||||||
|
|
||||||
impl Drop for Display {
|
impl Drop for Display {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
if self.inner.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.inner).Release();
|
(*self.inner).Release();
|
||||||
(*self.adapter).Release();
|
(*self.adapter).Release();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user