From b54d47796d2811f92826d7e8a4f3c149946815df Mon Sep 17 00:00:00 2001 From: sandmor Date: Sun, 22 Aug 2021 13:45:24 -0500 Subject: [PATCH] Fix transparency on X11 (#2006) * find transparent in x11 * remove debug hooks * update changelog * polish and failed to find visual warning --- CHANGELOG.md | 1 + src/platform_impl/linux/x11/window.rs | 46 +++++++++++++++++---------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 623cd1ee61..6605956a52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- On X11, select an appropriate visual for transparency if is requested - On Wayland and X11, fix diagonal window resize cursor orientation. - On macOS, drop the event callback before exiting. - On Android, implement `Window::request_redraw` diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 9f3d573695..247a289bc3 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -8,6 +8,7 @@ use std::{ ptr, slice, sync::Arc, }; +use x11_dl::xlib::TrueColor; use libc; use mio_misc::channel::Sender; @@ -180,6 +181,31 @@ impl UnownedWindow { }; // creating + let (visual, depth) = match pl_attribs.visual_infos { + Some(vi) => (vi.visual, vi.depth), + None if window_attrs.transparent == true => { + // Find a suitable visual + let mut vinfo = MaybeUninit::uninit(); + let vinfo_initialized = unsafe { + (xconn.xlib.XMatchVisualInfo)( + xconn.display, + screen_id, + 32, + TrueColor, + vinfo.as_mut_ptr(), + ) != 0 + }; + if vinfo_initialized { + let vinfo = unsafe { vinfo.assume_init() }; + (vinfo.visual, vinfo.depth) + } else { + debug!("Could not set transparency, because XMatchVisualInfo returned zero for the required parameters"); + (ffi::CopyFromParent as *mut ffi::Visual, ffi::CopyFromParent) + } + } + _ => (ffi::CopyFromParent as *mut ffi::Visual, ffi::CopyFromParent), + }; + let mut set_win_attr = { let mut swa: ffi::XSetWindowAttributes = unsafe { mem::zeroed() }; swa.colormap = if let Some(vi) = pl_attribs.visual_infos { @@ -187,6 +213,8 @@ impl UnownedWindow { let visual = vi.visual; (xconn.xlib.XCreateColormap)(xconn.display, root, visual, ffi::AllocNone) } + } else if window_attrs.transparent { + unsafe { (xconn.xlib.XCreateColormap)(xconn.display, root, visual, ffi::AllocNone) } } else { 0 }; @@ -220,23 +248,9 @@ impl UnownedWindow { dimensions.0 as c_uint, dimensions.1 as c_uint, 0, - match pl_attribs.visual_infos { - Some(vi) => vi.depth, - None => ffi::CopyFromParent, - }, + depth, ffi::InputOutput as c_uint, - // TODO: If window wants transparency and `visual_infos` is None, - // we need to find our own visual which has an `alphaMask` which - // is > 0, like we do in glutin. - // - // It is non obvious which masks, if any, we should pass to - // `XGetVisualInfo`. winit doesn't receive any info about what - // properties the user wants. Users should consider choosing the - // visual themselves as glutin does. - match pl_attribs.visual_infos { - Some(vi) => vi.visual, - None => ffi::CopyFromParent as *mut ffi::Visual, - }, + visual, window_attributes, &mut set_win_attr, )