rust-windowing / winit

Window handling library in pure Rust
https://docs.rs/winit/
Apache License 2.0
4.7k stars 886 forks source link

Transparent example not working #2502

Open mgalos999 opened 1 year ago

mgalos999 commented 1 year ago

When I run cargo run --example transparent instead of a transparent window I just get a white window with no decorations.

It seems the problem was introduced in this PR: https://github.com/rust-windowing/winit/pull/2419 If I revert to a commit before that PR was merged, then I see no GUI window showing up at all which I believe is the intended result (I see the icon in the taskbar and it appears in the alt+tab window list).

When I run the transparent example on the latest commit I just get a white window (with the expected icon in the taskbar)

I am running Windows 10.

mgalos999 commented 1 year ago

Ok I think I have a fix, but I'm not sure if it will really do the job.

I think you just have to insert this in src/platform_impl/windows.rs

if self.contains(WindowFlags::TRANSPARENT) {
    style_ex |= WS_EX_LAYERED;
}

Note you won't want to use the WS_EX_TRANSPARENT style since that doesn't actually make the window transparent, it just makes mouse clicks passthrough

msiglreith commented 1 year ago

thanks for the report. It should work fine when actually drawing something onto the window surface, which the examples don't do. With the changes from the PR the screens windows will be completely invisible for me, no matter what I draw on it.

amrbashir commented 1 year ago

It should work fine when actually drawing something onto the window surface

However this would be an overhead for apps that don't need to draw the window surface, for example when using Webview2.

Transparency used to work out of the box for undecorated windows before https://github.com/rust-windowing/winit/pull/1933 . I really don't know what caused the regression or if it can be fixed but it is the reason why I kept TAO (the winit fork for WRY) using subclasses.

This could also be a blocker for us to migrate back to using winit directly.

Edit: Seems it is indeed #2419 not #1933, I thought it was #1933 because at the time I was testing it along with #1891 which is similar to #2419

kchibisov commented 1 year ago

I might be not understand how transparency works on windows, but aren't you required to provide a buffer with alpha value in the end?

Is it just blending with black background now if you draw into subview(not sure how that called on windows, but that's my understanding of what happens). You might just clear it with fully transparent color it or do something like.

amrbashir commented 1 year ago

Webview2 works a bit differently. I don't remember the correct term for it but it is a sort of a child window which has its own window surface. So in order to have transparency, we would need to draw the window surface which is just a bit annoying since we don't need to draw the window surface for any other purpose.

This could also be a blocker for us to migrate back to using winit directly.

Also this was an overstatement from me, I think I wanted to say it will be a minor setback.

kchibisov commented 1 year ago

In general if you don't feel the root window with something it could contain random data leading to graphical artifacts. Conveniently some GPU drivers do clear the buffer with zeros for you, so you have some sort of initialized thingy, but it's not always the case and on linux users can disable that for example leading you to blending with random data.

I'm not an expert here, but you should always explicitly initialize the buffers you blend against.

ericguedespinto commented 1 year ago

Window transparency is broken on Macos as well. This is a regression as it works if I use winit legacy (0.19.5) after some tweaks to make the compiler happy

kchibisov commented 1 year ago

I'm not sure what are you talking about, transparency works just fine on all the available backends, only example is broken, nothing more. Real code with e.g. OpenGL is not affected.

ericguedespinto commented 1 year ago

The transparent example also does not work on macos.

I dug a little bit, and I believe the bug is with the platform_impl/window.rs where the code is using the setOpaque method of NSWindow. As far as I can tell, this method is deprecated and no longer exists, and the NSWindow API created using objc2 crate is out of date. Because of the way message passing works in objective-C, it just fails silently. Does anyone know how to set a transparent background in NSWindow in modern AppKit? I tried adding the API for alphaValue, and it worked, but I think alphaValue affects the whole window and not just the background.

ericguedespinto commented 1 year ago

I'm not sure what are you talking about, transparency works just fine on all the available backends, only example is broken, nothing more. Real code with e.g. OpenGL is not affected.

You mean that using with_transparent will not work but using openGL on the context directly will? Can you provide an example, please?

kchibisov commented 1 year ago

idk, just run https://github.com/rust-windowing/glutin example from here, it's transparent. There's also alacritty which uses Opaque hints and has transparency. Also, softbuffer, which we're using for examples don't support transparency at all as of now...

madsmtm commented 1 year ago

setOpaque definitely exists, it's just documented as opaque due to how Objective-C renames property setters.

Because of the way message passing works in objective-C, it just fails silently.

Nope, that would've thrown an error. It only does that if the receiver/window is NULL.

stefnotch commented 1 year ago

@ericguedespinto Do you have a minimal reproducible example for the MacOS behavior? If yes, could you open a new issue for that? If not, could you try out https://github.com/rust-windowing/winit/pull/3048 ?

CoryRobertson commented 9 months ago

are any workarounds available? Transparency also is not working for me as well.

orhun commented 9 months ago

having the same issue here, reported to RioTerm as well: https://github.com/raphamorim/rio/issues/361

raggi commented 4 months ago

idk, just run https://github.com/rust-windowing/glutin example from here, it's transparent. There's also alacritty which uses Opaque hints and has transparency. Also, softbuffer, which we're using for examples don't support transparency at all as of now...

image

Could you provide some more guidance?

TeamDman commented 4 months ago

can confirm the glutin example works for me

from their readme:

git clone https://github.com/rust-windowing/glutin
cd glutin
cargo run --example window

can correctly see my web browser through the transparent window

image

Edition Windows 10 Pro
Version 22H2
Installed on    ‎2020-‎11-‎03
OS build    19045.4291
Experience  Windows Feature Experience Pack 1000.19056.1000.0
raggi commented 4 months ago

Quite right, I forgot versioning information, doubling down:

image

~\src\glutin> cargo run --example window
warning: unused import: `std::mem`
 --> C:\Users\raggi\src\glutin\target\debug\build\glutin_wgl_sys-580181e13c8eaeb7\out/wgl_bindings.rs:3:21
  |
3 |             pub use std::mem;
  |                     ^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: `glutin_wgl_sys` (lib) generated 1 warning (run `cargo fix --lib -p glutin_wgl_sys`
to apply 1 suggestion)
    Finished dev [unoptimized + debuginfo] target(s) in 2.01s
     Running `target\debug\examples\window.exe`
Picked a config with 16 samples
Running on NVIDIA GeForce RTX 4090/PCIe/SSE2
OpenGL Version 3.3.0 NVIDIA 551.86
Shaders version on 3.30 NVIDIA via Cg compiler
OS Name:                   Microsoft Windows 11 Pro
OS Version:                10.0.22631 N/A Build 22631
~\src\glutin> rustc --version
rustc 1.77.2 (25ef9e3d8 2024-04-09)
~\src\glutin> g log --oneline -n1
9228126 (HEAD -> master, origin/master, origin/HEAD) ci: add typos

Also to confirm, here's transparency effects from native composited windows: image

msiglreith commented 4 months ago

You might have to check your NVIDIA driver settings in case some presentation compatibility has been set. The WSI parts of OpenGL and Vulkan are unfortunately not great. Using DXGI/DirectComposition should give more control.

han1548772930 commented 3 months ago

Is there any solution at present?

Long0x0 commented 1 week ago

This has been fixed? Just set the alpha channel of color DARK_GRAY and it's working for me.

Tested with v0.30.5 on Windows11:

use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowId};

#[path = "util/fill.rs"]
mod fill;

#[derive(Default)]
struct State {
    window: Option<Window>,
}

impl ApplicationHandler for State {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        let attributes = Window::default_attributes().with_transparent(true);
        self.window = Some(event_loop.create_window(attributes).unwrap());
    }
    fn window_event(
        &mut self,
        event_loop: &ActiveEventLoop,
        _window_id: WindowId,
        event: WindowEvent,
    ) {
        let window = self.window.as_ref().unwrap();
        match event {
            WindowEvent::CloseRequested => event_loop.exit(),
            WindowEvent::RedrawRequested => {
                fill::fill_window(&window);
            },
            _ => (),
        }
    }
}

fn main() {
    let event_loop = EventLoop::new().unwrap();
    let mut state = State::default();
    let _ = event_loop.run_app(&mut state);
}

Screenshot: