1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-28 07:55:03 +03:00

window: allow window layer to hold per-window config

This is to allow for eg: hotkey to change window decorations
(https://wezfurlong.org/wezterm/config/lua/window/set_config_overrides.html)

So far only macos actually keeps a per-window config.
Hopefully this still compiles for windows and x11.
This commit is contained in:
Wez Furlong 2021-03-04 23:05:44 -08:00
parent a5bc89e6d3
commit cfed798e79
10 changed files with 123 additions and 39 deletions

View File

@ -238,6 +238,7 @@ impl WindowCallbacks for TermWindow {
let clipboard_contents = Arc::clone(&self.clipboard_contents);
let dimensions = self.dimensions.clone();
let mux_window_id = self.mux_window_id;
let config = self.config.clone();
let guts = Box::new(Self {
window: None,
@ -287,6 +288,7 @@ impl WindowCallbacks for TermWindow {
dimensions.pixel_width,
dimensions.pixel_height,
guts,
Some(&crate::window_config::ConfigInstance::new(config)),
)?;
Self::apply_icon(&window)?;
@ -492,6 +494,7 @@ impl TermWindow {
last_blink_paint: Instant::now(),
last_status_call: Instant::now(),
}),
Some(&crate::window_config::ConfigInstance::new(config)),
)?;
Self::apply_icon(&window)?;
@ -755,7 +758,7 @@ impl TermWindow {
self.apply_scale_change(&dimensions, self.fonts.get_font_scale());
self.apply_dimensions(&dimensions, Some(cell_dims));
if let Some(window) = self.window.as_ref() {
window.config_did_change();
window.config_did_change(&crate::window_config::ConfigInstance::new(config));
window.invalidate();
}
}

View File

@ -1,31 +1,43 @@
use ::window::configuration::WindowConfiguration;
use config::configuration;
use config::{configuration, ConfigHandle};
use std::sync::Arc;
/// An instance that always returns the global configuration values
pub struct ConfigBridge;
impl WindowConfiguration for ConfigBridge {
/// Returns the config from the given config handle
pub struct ConfigInstance(pub ConfigHandle);
impl ConfigInstance {
pub fn new(h: ConfigHandle) -> Arc<dyn WindowConfiguration + Send + Sync> {
let s = Self(h);
Arc::new(s)
}
}
impl WindowConfiguration for ConfigInstance {
fn use_ime(&self) -> bool {
configuration().use_ime
self.0.use_ime
}
fn use_dead_keys(&self) -> bool {
configuration().use_dead_keys
self.0.use_dead_keys
}
fn send_composed_key_when_left_alt_is_pressed(&self) -> bool {
configuration().send_composed_key_when_left_alt_is_pressed
self.0.send_composed_key_when_left_alt_is_pressed
}
fn send_composed_key_when_right_alt_is_pressed(&self) -> bool {
configuration().send_composed_key_when_right_alt_is_pressed
self.0.send_composed_key_when_right_alt_is_pressed
}
fn enable_wayland(&self) -> bool {
configuration().enable_wayland
self.0.enable_wayland
}
fn prefer_egl(&self) -> bool {
configuration().prefer_egl
self.0.prefer_egl
}
fn prefer_swrast(&self) -> bool {
@ -38,18 +50,64 @@ impl WindowConfiguration for ConfigBridge {
return true;
}
}
configuration().front_end == config::FrontEndSelection::Software
self.0.front_end == config::FrontEndSelection::Software
}
fn native_macos_fullscreen_mode(&self) -> bool {
configuration().native_macos_fullscreen_mode
self.0.native_macos_fullscreen_mode
}
fn window_background_opacity(&self) -> f32 {
configuration().window_background_opacity
self.0.window_background_opacity
}
fn decorations(&self) -> ::window::WindowDecorations {
configuration().window_decorations
self.0.window_decorations
}
}
fn global() -> ConfigInstance {
ConfigInstance(configuration())
}
impl WindowConfiguration for ConfigBridge {
fn use_ime(&self) -> bool {
global().use_ime()
}
fn use_dead_keys(&self) -> bool {
global().use_dead_keys()
}
fn send_composed_key_when_left_alt_is_pressed(&self) -> bool {
global().send_composed_key_when_left_alt_is_pressed()
}
fn send_composed_key_when_right_alt_is_pressed(&self) -> bool {
global().send_composed_key_when_right_alt_is_pressed()
}
fn enable_wayland(&self) -> bool {
global().enable_wayland()
}
fn prefer_egl(&self) -> bool {
global().prefer_egl()
}
fn prefer_swrast(&self) -> bool {
global().prefer_swrast()
}
fn native_macos_fullscreen_mode(&self) -> bool {
global().native_macos_fullscreen_mode()
}
fn window_background_opacity(&self) -> f32 {
global().window_background_opacity()
}
fn decorations(&self) -> ::window::WindowDecorations {
global().decorations()
}
}

View File

@ -64,6 +64,7 @@ async fn spawn_window() -> Result<(), Box<dyn std::error::Error>> {
allow_close: false,
cursor_pos: Point::new(100, 200),
}),
None,
)?;
eprintln!("before show");

View File

@ -170,6 +170,7 @@ fn spawn_window() -> anyhow::Result<()> {
cursor_pos: Point::new(100, 200),
gl: None,
}),
None,
)?;
win.show();

View File

@ -55,11 +55,13 @@ lazy_static::lazy_static! {
static ref CONFIG: Mutex<Arc<dyn WindowConfiguration + Send + Sync>> = default_config();
}
pub(crate) fn config() -> Arc<dyn WindowConfiguration + Send + Sync> {
pub type WindowConfigHandle = Arc<dyn WindowConfiguration + Send + Sync>;
pub(crate) fn config() -> WindowConfigHandle {
Arc::clone(&CONFIG.lock().unwrap())
}
fn default_config() -> Mutex<Arc<dyn WindowConfiguration + Send + Sync>> {
fn default_config() -> Mutex<WindowConfigHandle> {
struct DefConfig;
impl WindowConfiguration for DefConfig {}
Mutex::new(Arc::new(DefConfig))

View File

@ -8,7 +8,7 @@ pub mod os;
mod spawn;
mod timerlist;
use configuration::config;
use configuration::{config, WindowConfigHandle};
#[cfg(target_os = "macos")]
pub const DEFAULT_DPI: f64 = 72.0;
@ -204,7 +204,7 @@ pub trait WindowOps {
Future::ok(())
}
fn config_did_change(&self) -> Future<()> {
fn config_did_change(&self, _config: &WindowConfigHandle) -> Future<()> {
Future::ok(())
}
}
@ -249,5 +249,5 @@ pub trait WindowOpsMut {
fn toggle_fullscreen(&mut self) {}
fn config_did_change(&mut self) {}
fn config_did_change(&mut self, _config: &WindowConfigHandle) {}
}

View File

@ -6,7 +6,7 @@ use crate::connection::ConnectionOps;
use crate::{
config, Clipboard, Connection, Dimensions, KeyCode, KeyEvent, Modifiers, MouseButtons,
MouseCursor, MouseEvent, MouseEventKind, MousePress, Point, Rect, ScreenPoint, Size,
WindowCallbacks, WindowDecorations, WindowOps, WindowOpsMut,
WindowCallbacks, WindowConfigHandle, WindowDecorations, WindowOps, WindowOpsMut,
};
use anyhow::{anyhow, bail, ensure};
use cocoa::appkit::{
@ -33,6 +33,7 @@ use std::cell::RefCell;
use std::ffi::c_void;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Instant;
fn round_away_from_zerof(value: f64) -> f64 {
@ -317,6 +318,7 @@ pub(crate) struct WindowInner {
window_id: usize,
view: StrongPtr,
window: StrongPtr,
config: WindowConfigHandle,
}
fn function_key_to_keycode(function_key: char) -> KeyCode {
@ -356,9 +358,15 @@ impl Window {
width: usize,
height: usize,
callbacks: Box<dyn WindowCallbacks>,
config: Option<&WindowConfigHandle>,
) -> anyhow::Result<Window> {
let config = match config {
Some(c) => Arc::clone(c),
None => crate::config(),
};
unsafe {
let style_mask = decoration_to_mask(config().decorations());
let style_mask = decoration_to_mask(config.decorations());
let rect = NSRect::new(
NSPoint::new(0., 0.),
NSSize::new(width as f64, height as f64),
@ -381,6 +389,7 @@ impl Window {
key_is_down: None,
dead_pending: None,
fullscreen: None,
config: Arc::clone(&config),
}));
let window: id = msg_send![get_window_class(), alloc];
@ -442,13 +451,14 @@ impl Window {
window_id,
window,
view,
config: Arc::clone(&config),
}));
conn.windows
.borrow_mut()
.insert(window_id, Rc::clone(&window_inner));
let window = Window(window_id);
window.config_did_change();
window.config_did_change(&config);
inner.borrow_mut().enable_opengl()?;
// Synthesize a resize event immediately; this allows
@ -574,9 +584,10 @@ impl WindowOps for Window {
})
}
fn config_did_change(&self) -> Future<()> {
fn config_did_change(&self, config: &WindowConfigHandle) -> Future<()> {
let config = Arc::clone(config);
Connection::with_window_inner(self.0, move |inner| {
inner.config_did_change();
inner.config_did_change(&config);
Ok(())
})
}
@ -627,7 +638,7 @@ impl WindowInner {
fn apply_decorations(&mut self) {
if !self.is_fullscreen() {
let mask = decoration_to_mask(config().decorations());
let mask = decoration_to_mask(self.config.decorations());
unsafe {
self.window.setStyleMask_(mask);
/*
@ -690,7 +701,7 @@ impl WindowInner {
// Restore prior dimensions
self.window.orderOut_(nil);
self.window
.setStyleMask_(decoration_to_mask(config().decorations()));
.setStyleMask_(decoration_to_mask(self.config.decorations()));
self.window.setFrame_display_(saved_rect, YES);
self.window.makeKeyAndOrderFront_(nil);
self.window.setOpaque_(NO);
@ -726,7 +737,7 @@ impl WindowInner {
}
fn update_window_shadow(&mut self) {
let is_opaque = if config().window_background_opacity() >= 1.0 {
let is_opaque = if self.config.window_background_opacity() >= 1.0 {
YES
} else {
NO
@ -826,7 +837,7 @@ impl WindowOpsMut for WindowInner {
if let Some(window_view) = WindowView::get_this(unsafe { &**self.view }) {
window_view.inner.borrow_mut().text_cursor_position = cursor;
}
if config().use_ime() {
if self.config.use_ime() {
unsafe {
let input_context: id = msg_send![&**self.view, inputContext];
let () = msg_send![input_context, invalidateCharacterCoordinates];
@ -835,7 +846,7 @@ impl WindowOpsMut for WindowInner {
}
fn toggle_fullscreen(&mut self) {
let native_fullscreen = config().native_macos_fullscreen_mode();
let native_fullscreen = self.config.native_macos_fullscreen_mode();
// If they changed their config since going full screen, be sure
// to undo whichever fullscreen mode they had active rather than
@ -852,7 +863,11 @@ impl WindowOpsMut for WindowInner {
}
}
fn config_did_change(&mut self) {
fn config_did_change(&mut self, config: &WindowConfigHandle) {
self.config = Arc::clone(config);
if let Some(window_view) = WindowView::get_this(unsafe { &**self.view }) {
window_view.inner.borrow_mut().config = Arc::clone(config);
}
self.update_window_shadow();
self.apply_decorations();
}
@ -900,6 +915,8 @@ struct Inner {
/// When using simple fullscreen mode, this tracks
/// the window dimensions that need to be restored
fullscreen: Option<NSRect>,
config: WindowConfigHandle,
}
#[repr(C)]
@ -1000,7 +1017,7 @@ impl Inner {
let mods = key_modifiers(modifier_flags);
let config = config();
let config = &self.config;
let use_dead_keys = if !config.use_dead_keys() {
false

View File

@ -514,7 +514,7 @@ impl WindowOpsMut for WindowInner {
imc.set_position(cursor.origin.x.max(0) as i32, cursor.origin.y.max(0) as i32);
}
fn config_did_change(&mut self) {
fn config_did_change(&mut self, _config: &WindowConfigHandle) {
self.apply_decoration();
}
@ -615,9 +615,10 @@ impl WindowOps for Window {
})
}
fn config_did_change(&self) -> Future<()> {
fn config_did_change(&self, config: &WindowConfigHandle) -> Future<()> {
let config = Arc::clone(config);
Connection::with_window_inner(self.0, move |inner| {
inner.config_did_change();
inner.config_did_change(&config);
Ok(())
})
}

View File

@ -849,7 +849,7 @@ impl WindowOpsMut for XWindowInner {
self.set_fullscreen_hint(!fullscreen).ok();
}
fn config_did_change(&mut self) {
fn config_did_change(&mut self, _config: &WindowConfigHandle) {
let _ = self.adjust_decorations(config().decorations());
}
@ -935,9 +935,10 @@ impl WindowOps for XWindow {
})
}
fn config_did_change(&self) -> Future<()> {
fn config_did_change(&self, config: &WindowConfigHandle) -> Future<()> {
let config = Arc::clone(config);
XConnection::with_window_inner(self.0, |inner| {
inner.config_did_change();
inner.config_did_change(&config);
Ok(())
})
}

View File

@ -142,11 +142,11 @@ impl WindowOps for Window {
}
}
fn config_did_change(&self) -> Future<()> {
fn config_did_change(&self, config: &WindowConfigHandle) -> Future<()> {
match self {
Self::X11(x) => x.config_did_change(),
Self::X11(x) => x.config_did_change(config),
#[cfg(feature = "wayland")]
Self::Wayland(w) => w.config_did_change(),
Self::Wayland(w) => w.config_did_change(config),
}
}