Add Window::set_transparent

Provide a hint to system compositor whether the window is transparent or
not. Only implemented on macOS and Wayland for now.
This commit is contained in:
Kirill Chibisov 2023-01-15 23:39:36 +03:00 committed by GitHub
parent 6f60c7a6cc
commit 62ce14a013
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 84 additions and 1 deletions

View file

@ -324,6 +324,11 @@ impl Window {
x11_or_wayland!(match self; Window(w) => w.set_title(title));
}
#[inline]
pub fn set_transparent(&self, transparent: bool) {
x11_or_wayland!(match self; Window(w) => w.set_transparent(transparent));
}
#[inline]
pub fn set_visible(&self, visible: bool) {
x11_or_wayland!(match self; Window(w) => w.set_visible(visible))

View file

@ -431,6 +431,9 @@ impl<T: 'static> EventLoop<T> {
window_handle.window.resize(size.width, size.height);
window_handle.window.refresh();
// Update the opaque region.
window_handle.set_transparent(window_handle.transparent.get());
// Mark that refresh isn't required, since we've done it right now.
state
.window_user_requests

View file

@ -261,6 +261,9 @@ impl Window {
window_requests.clone(),
);
// Set opaque region.
window_handle.set_transparent(attributes.transparent);
// Set resizable state, so we can determine how to handle `Window::set_inner_size`.
window_handle.is_resizable.set(attributes.resizable);
@ -332,6 +335,11 @@ impl Window {
self.send_request(WindowRequest::Title(title.to_owned()));
}
#[inline]
pub fn set_transparent(&self, transparent: bool) {
self.send_request(WindowRequest::Transparent(transparent));
}
#[inline]
pub fn set_visible(&self, _visible: bool) {
// Not possible on Wayland.

View file

@ -80,6 +80,9 @@ pub enum WindowRequest {
/// Enable IME on the given window.
AllowIme(bool),
/// Mark the window as opaque.
Transparent(bool),
/// Request Attention.
///
/// `None` unsets the attention request.
@ -154,6 +157,9 @@ pub struct WindowHandle {
/// Allow IME events for that window.
pub ime_allowed: Cell<bool>,
/// Wether the window is transparent.
pub transparent: Cell<bool>,
/// Visible cursor or not.
cursor_visible: Cell<bool>,
@ -194,6 +200,7 @@ impl WindowHandle {
pending_window_requests,
cursor_icon: Cell::new(CursorIcon::Default),
is_resizable: Cell::new(true),
transparent: Cell::new(false),
cursor_grab_mode: Cell::new(CursorGrabMode::None),
cursor_visible: Cell::new(true),
pointers: Vec::new(),
@ -349,6 +356,19 @@ impl WindowHandle {
}
}
pub fn set_transparent(&self, transparent: bool) {
self.transparent.set(transparent);
let surface = self.window.surface();
if transparent {
surface.set_opaque_region(None);
} else {
let region = self.compositor.create_region();
region.add(0, 0, i32::MAX, i32::MAX);
surface.set_opaque_region(Some(&region.detach()));
region.destroy();
}
}
pub fn set_ime_allowed(&self, allowed: bool, event_sink: &mut EventSink) {
if self.ime_allowed.get() == allowed {
return;
@ -452,6 +472,13 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
WindowRequest::Minimize => {
window_handle.window.set_minimized();
}
WindowRequest::Transparent(transparent) => {
window_handle.set_transparent(transparent);
// This requires surface commit.
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.redraw_requested = true;
}
WindowRequest::Decorate(decorate) => {
let decorations = match decorate {
true => Decorations::FollowServer,

View file

@ -903,6 +903,9 @@ impl UnownedWindow {
.expect("Failed to set window title");
}
#[inline]
pub fn set_transparent(&self, _transparent: bool) {}
fn set_decorations_inner(&self, decorations: bool) -> util::Flusher<'_> {
self.shared_state_lock().is_decorated = decorations;
let mut hints = self.xconn.get_motif_hints(self.xwindow);