1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

macos: implement opacity for CGL and Metal

There's a few different knobs to turn, but this
commit turns them and we're now able to respect
opacity settings for both OpenGL/CGL and Metal
renderers.

closes: #141
This commit is contained in:
Wez Furlong 2020-10-18 14:00:06 -07:00
parent 2364b0a20e
commit 191b047126
3 changed files with 60 additions and 21 deletions

View File

@ -13,6 +13,9 @@ brief notes about them may accumulate here.
* New: split/pane support!
See [#157](https://github.com/wez/wezterm/issues/157) for
overall status and additional information.
* New: `window_background_opacity`, `window_background_image`
and `window_background_tint` options to control using background
images, transparent windows. [More info](https://github.com/wez/wezterm/commit/f2cbc182cdbf4463b5f80bee7cb651bb7e67024b)
* The GUI layer now normalizes SHIFT state for keyboard processing.
If a keypress is ASCII uppercase and SHIFT is held then the
SHIFT modifier is removed from the set of active modifiers. This

View File

@ -2588,11 +2588,15 @@ impl TermWindow {
pos: &PositionedPane,
frame: &mut glium::Frame,
) -> anyhow::Result<()> {
let config = configuration();
let palette = pos.pane.palette();
let background_color = palette.resolve_bg(wezterm_term::color::ColorAttribute::Default);
let background_alpha = (config.window_background_opacity * 255.0) as u8;
let background = rgbcolor_alpha_to_window_color(palette.background, background_alpha);
if pos.index == 0 {
let (r, g, b, a) = background_color.to_tuple_rgba();
let (r, g, b, a) = background.to_tuple_rgba();
frame.clear_color_srgb(r, g, b, a);
}
@ -2607,7 +2611,6 @@ impl TermWindow {
let current_viewport = self.get_viewport(pos.pane.pane_id());
let (stable_top, lines);
let dims = term.get_dimensions();
let config = configuration();
{
let stable_range = match current_viewport {
@ -2626,8 +2629,6 @@ impl TermWindow {
let cursor_border_color = rgbcolor_to_window_color(palette.cursor_border);
let foreground = rgbcolor_to_window_color(palette.foreground);
let background_alpha = (config.window_background_opacity * 255.0) as u8;
let background = rgbcolor_alpha_to_window_color(palette.background, background_alpha);
if self.show_tab_bar && pos.index == 0 {
let tab_dims = RenderableDimensions {

View File

@ -6,9 +6,9 @@ use crate::bitmaps::Image;
use crate::connection::ConnectionOps;
use crate::os::macos::bitmap::BitmapRef;
use crate::{
BitmapImage, Clipboard, Color, Connection, Dimensions, KeyCode, KeyEvent, Modifiers,
MouseButtons, MouseCursor, MouseEvent, MouseEventKind, MousePress, Operator, PaintContext,
Point, Rect, ScreenPoint, Size, WindowCallbacks, WindowOps, WindowOpsMut,
is_egl_preferred, BitmapImage, Clipboard, Color, Connection, Dimensions, KeyCode, KeyEvent,
Modifiers, MouseButtons, MouseCursor, MouseEvent, MouseEventKind, MousePress, Operator,
PaintContext, Point, Rect, ScreenPoint, Size, WindowCallbacks, WindowOps, WindowOpsMut,
};
use anyhow::{anyhow, bail, ensure};
use cocoa::appkit::{
@ -131,17 +131,6 @@ mod opengl {
/// The ANGLE EGL implementation wants a CALayer descendant passed
/// as the EGLNativeWindowType.
pub fn create(view: id) -> anyhow::Result<Self> {
let layer: id;
// ANGLE wants a layer, so tell the view to create one.
// Importantly, we must set its scale to 1.0 prior to initializing
// EGL to prevent undesirable scaling.
unsafe {
let _: () = msg_send![view, setWantsLayer: YES];
layer = msg_send![view, layer];
let _: () = msg_send![layer, setContentsScale: 1.0f64];
};
let behavior = if cfg!(debug_assertions) {
glium::debug::DebugCallbackBehavior::DebugMessageOnError
} else {
@ -149,8 +138,38 @@ mod opengl {
};
// Let's first try to initialize EGL...
let (context, backend) = match crate::egl::GlState::create(None, layer as *const c_void)
{
let (context, backend) = match if is_egl_preferred() {
// ANGLE wants a layer, so tell the view to create one.
// Importantly, we must set its scale to 1.0 prior to initializing
// EGL to prevent undesirable scaling.
let layer: id;
unsafe {
let _: () = msg_send![view, setWantsLayer: YES];
layer = msg_send![view, layer];
let _: () = msg_send![layer, setContentsScale: 1.0f64];
let _: () = msg_send![layer, setOpaque: NO];
};
let state = crate::egl::GlState::create(None, layer as *const c_void);
if state.is_ok() {
// ANGLE will create a CAMetalLayer as a sublayer of our provided
// layer. Even though CALayer defaults to !opaque, CAMetalLayer
// defaults to opaque, so we need to find that layer and fix
// the opacity so that our alpha values are respected.
unsafe {
let sublayers: id = msg_send![layer, sublayers];
let layer_count = sublayers.count();
for i in 0..layer_count {
let layer = sublayers.objectAtIndex(i);
let _: () = msg_send![layer, setOpaque: NO];
}
}
}
state
} else {
Err(anyhow!("prefers not to use EGL"))
} {
Ok(backend) => {
let backend = Rc::new(backend);
let context = unsafe {
@ -220,7 +239,14 @@ mod opengl {
)
};
ensure!(!gl_context.is_null(), "failed to create NSOpenGLContext");
unsafe {
let opaque: cgl::GLint = 0;
gl_context.setValues_forParameter_(
&opaque,
cocoa::appkit::NSOpenGLContextParameter::NSOpenGLCPSurfaceOpacity,
);
gl_context.setView_(view);
}
@ -378,6 +404,14 @@ impl Window {
let _: () = msg_send![*window, setTabbingMode:2 /* NSWindowTabbingModeDisallowed */];
window.setReleasedWhenClosed_(NO);
window.setOpaque_(NO);
// window.setHasShadow_(NO);
let ns_color: id = msg_send![Class::get("NSColor").unwrap(), alloc];
window.setBackgroundColor_(cocoa::appkit::NSColor::clearColor(ns_color));
// We could set this, but it makes the entire window, including
// its titlebar, opaque to this fixed degree.
// window.setAlphaValue_(0.4);
// Window positioning: the first window opens up in the center of
// the screen. Subsequent windows will be offset from the position
@ -1045,7 +1079,7 @@ impl WindowView {
// Tell the window/view/layer stuff that we only have a single opaque
// thing in the window so that it can optimize rendering
extern "C" fn is_opaque(_this: &Object, _sel: Sel) -> BOOL {
YES
NO
}
// Don't use Cocoa native window tabbing
@ -1483,6 +1517,7 @@ impl WindowView {
sel!(isFlipped),
Self::is_flipped as extern "C" fn(&Object, Sel) -> BOOL,
);
cls.add_method(
sel!(isOpaque),
Self::is_opaque as extern "C" fn(&Object, Sel) -> BOOL,