From 5725f5812ca5e8d7d992da4ac66aa454a8a9a9ad Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 21 Dec 2020 06:40:22 +0000 Subject: [PATCH] Fix artifacts on macOS with transparent windows Due to the way macOS draws shadows for transparent windows, resizing them will lead to text artifacts remaining present after a window has been resized. The `invalidateShadow` call is used whenever the opacity isn't `1.0` to make sure these shadows are cleared before redrawing, so no artifacts remain when resizing transparent windows. Fixes #889. --- CHANGELOG.md | 1 + Cargo.lock | 2 ++ alacritty/Cargo.toml | 2 ++ alacritty/src/display.rs | 6 ++++++ alacritty/src/window.rs | 19 +++++++++++++++++++ 5 files changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae6deaea..d9701053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - High CPU usage on BSD with live config reload enabled - Alacritty not discarding invalid escape sequences starting with ESC - Crash due to clipboard not being properly released on Wayland +- Shadow artifacts when resizing transparent windows on macOS ### Removed diff --git a/Cargo.lock b/Cargo.lock index f3aa5acd..f9b53890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,7 @@ dependencies = [ "alacritty_terminal", "bitflags", "clap", + "cocoa 0.24.0", "copypasta", "crossfont", "dirs", @@ -42,6 +43,7 @@ dependencies = [ "objc", "parking_lot", "png", + "raw-window-handle", "serde", "serde_json", "serde_yaml", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 6e833f34..4810ced4 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -46,6 +46,8 @@ xdg = "2" png = { version = "0.16.8", default-features = false, optional = true } [target.'cfg(target_os = "macos")'.dependencies] +raw-window-handle = "0.3.3" +cocoa = "0.24.0" objc = "0.2.2" [target.'cfg(not(any(target_os="windows", target_os="macos")))'.dependencies] diff --git a/alacritty/src/display.rs b/alacritty/src/display.rs index 1fe1d2de..fb82b9f8 100644 --- a/alacritty/src/display.rs +++ b/alacritty/src/display.rs @@ -610,6 +610,12 @@ impl Display { #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] self.request_frame(&self.window); + // Clear window shadows to prevent shadow artifacts on macOS. + #[cfg(target_os = "macos")] + if config.ui_config.background_opacity() < 1.0 { + self.window.invalidate_shadow(); + } + self.window.swap_buffers(); #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] diff --git a/alacritty/src/window.rs b/alacritty/src/window.rs index f4a38183..1b874d15 100644 --- a/alacritty/src/window.rs +++ b/alacritty/src/window.rs @@ -31,6 +31,8 @@ use { use std::fmt::{self, Display, Formatter}; +#[cfg(target_os = "macos")] +use cocoa::base::id; use glutin::dpi::{PhysicalPosition, PhysicalSize}; use glutin::event_loop::EventLoop; #[cfg(target_os = "macos")] @@ -41,6 +43,10 @@ use glutin::window::{ CursorIcon, Fullscreen, UserAttentionType, Window as GlutinWindow, WindowBuilder, WindowId, }; use glutin::{self, ContextBuilder, PossiblyCurrent, WindowedContext}; +#[cfg(target_os = "macos")] +use objc::{msg_send, sel, sel_impl}; +#[cfg(target_os = "macos")] +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; #[cfg(windows)] use winapi::shared::minwindef::WORD; @@ -435,6 +441,19 @@ impl Window { self.windowed_context.resize(size); } + /// Force macOS to clear shadow of transparent windows. + #[cfg(target_os = "macos")] + pub fn invalidate_shadow(&self) { + let raw_window = match self.window().raw_window_handle() { + RawWindowHandle::MacOS(handle) => handle.ns_window as id, + _ => return, + }; + + unsafe { + let _: () = msg_send![raw_window, invalidateShadow]; + } + } + fn window(&self) -> &GlutinWindow { self.windowed_context.window() }