Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to access WindowHandle::get_hwnd on windows? #1505

Closed
zumoshi opened this issue Jan 5, 2021 · 5 comments
Closed

Any way to access WindowHandle::get_hwnd on windows? #1505

zumoshi opened this issue Jan 5, 2021 · 5 comments

Comments

@zumoshi
Copy link

zumoshi commented Jan 5, 2021

Hi,
I need a reference to HWND to set display affinity:

unsafe{
    winapi::um::winuser::SetWindowDisplayAffinity(self.handle.get_hwnd().unwrap(), winapi::um::winuser::WDA_MONITOR);
}

Currently, I patched window.rs to access it:

diff --git a/druid-shell/src/window.rs b/druid-shell/src/window.rs
index 9420efc..4a6326f 100644
--- a/druid-shell/src/window.rs
+++ b/druid-shell/src/window.rs
@@ -144,6 +144,8 @@ pub enum WindowState {
 #[derive(Clone, Default)]
 pub struct WindowHandle(platform::WindowHandle);

+use winapi::shared::windef::*;
+
 impl WindowHandle {
     /// Make this window visible.
     ///
@@ -321,6 +323,11 @@ impl WindowHandle {
         self.0.get_idle_handle().map(IdleHandle)
     }

+    /// patch to expose HWND
+    pub fn get_hwnd(&self) -> Option<HWND> {
+        self.0.get_hwnd()
+    }
+
     /// Get the DPI scale of the window.
     ///
     /// The returned [`Scale`](crate::Scale) is a copy and thus its information will be stale after

Did I miss a way to access it without patching the library? If not is there a better way that won't break cross-platform features that would allow direct access to HWND under a #[cfg(target_os = "windows")]?
Or any plans to add a safe wrapper for SetWindowDisplayAffinity?

Thanks.

@djeedai
Copy link
Contributor

djeedai commented Jan 5, 2021

There's no direct access because this breaks encapsulation and cross-platform. A better way I think to do that is to expose the handle via https://docs.rs/raw-window-handle/0.3.3; I did that for #1462 on Windows, although it's not published anywhere yet. The code looks like this:

unsafe impl HasRawWindowHandle for WindowHandle {
    fn raw_window_handle(&self) -> RawWindowHandle {
        if let Some(hwnd) = self.0.get_hwnd() {
            let handle = raw_window_handle::windows::WindowsHandle {
                hwnd: hwnd as *mut libc::c_void,
                hinstance: unsafe {
                    winapi::um::libloaderapi::GetModuleHandleW(0 as winapi::um::winnt::LPCWSTR)
                        as *mut libc::c_void
                },
                ..raw_window_handle::windows::WindowsHandle::empty()
            };
            RawWindowHandle::Windows(handle)
        } else {
            panic!()
        }
    }
}

If this is something the devs are interesting in merging I can make a PR just for that part and rebase my work on top of it.

I am curious why you need SetWindowDisplayAffinity(). Also I think this may break depending on what backend is used. Reading the documentation, it says this only works if DWM is composing the Desktop; no idea what other options there are, but it's unclear to me what happens when using e.g. DirectX for window rendering.

@zumoshi
Copy link
Author

zumoshi commented Jan 5, 2021

I am curious why you need SetWindowDisplayAffinity()

Preventing screenshots of confidential information. A built-in version of opswat or screenwings. The equivalent API in UWP would be IsScreenCaptureEnabled

it says this only works if DWM is composing the Desktop

Given the nature of my use case, it is preferable if the application fails rather than the data leaked. But there should be alternative ways to achieve the same thing under other renderers.

the devs are interesting in merging

While ideally there wouldn't be any need for it, it is unfeasble to implement all the possible Windows-specific flags/options that need an HWND in a cross-platform way. IMHO allowing the library users to access the unsafe underlying APIs is better than just not being able to do it.

@djeedai
Copy link
Contributor

djeedai commented Jan 10, 2021

it says this only works if DWM is composing the Desktop

Actually reading more docs, DWM is always compositing on Windows 10, and I think on 8.1 too.

@cmyr
Copy link
Member

cmyr commented Jan 11, 2021

I want a principled way of doing these sorts of platform dependent things. I do agree that they're desirable. The thing I keep coming back to is the platform-specific extensions in the rust stdlib, like DirBuilderExt.

@cmyr
Copy link
Member

cmyr commented Apr 1, 2021

support for the HasRawWindowHandle trait was added in #1586 and #1667

@cmyr cmyr closed this as completed Apr 1, 2021
djeedai added a commit to djeedai/druid that referenced this issue Jun 20, 2021
Expose the `HasRawWindowHandle` trait impl of druid-shell for
`WindowHandle` into druid itself, so druid users can access it. This
is also under a `raw-win-handle` feature, like the druid-shell one.

Bug: linebender#1505
djeedai added a commit to djeedai/druid that referenced this issue Jun 20, 2021
Expose the `HasRawWindowHandle` trait impl of druid-shell for
`WindowHandle` into druid itself, so druid users can access it. This
is also under a `raw-win-handle` feature, like the druid-shell one.

Bug: linebender#1505
playmer pushed a commit to playmer/druid that referenced this issue Jul 17, 2021
Expose the `HasRawWindowHandle` trait impl of druid-shell for
`WindowHandle` into druid itself, so druid users can access it. This
is also under a `raw-win-handle` feature, like the druid-shell one.

Bug: linebender#1505
djeedai added a commit to djeedai/druid that referenced this issue Jul 22, 2021
Expose the `HasRawWindowHandle` trait impl of druid-shell for
`WindowHandle` into druid itself, so druid users can access it. This
is also under a `raw-win-handle` feature, like the druid-shell one.

Bug: linebender#1505
cmyr pushed a commit that referenced this issue Jul 23, 2021
Expose the `HasRawWindowHandle` trait impl of druid-shell for
`WindowHandle` into druid itself, so druid users can access it. This
is also under a `raw-win-handle` feature, like the druid-shell one.

Bug: #1505
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants