aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Moon <joe@xoxomoon.com>2018-09-20 08:24:26 -0700
committerJoe Wilm <jwilm@users.noreply.github.com>2018-09-20 08:24:26 -0700
commit3b46859eceea39afb8bbc760235cc15de78d3ff3 (patch)
treef17d8b715a9ebb50dac94069f9647c5f09b34840
parent641f3291eb918afdc513daa89dbcabfcc202e077 (diff)
downloadalacritty-3b46859eceea39afb8bbc760235cc15de78d3ff3.tar.gz
alacritty-3b46859eceea39afb8bbc760235cc15de78d3ff3.zip
Improve window.decorations options: (#1241)
The decorations config was changed from a bool to an enum. `full` has taken the place of `true`, and `none`, has replaced `false`. On macOS, there are now options for `transparent` and `buttonless`. These options are explained in both the CHANGELOG and in the configuration files.
-rw-r--r--CHANGELOG.md9
-rw-r--r--alacritty.yml6
-rw-r--r--alacritty_macos.yml10
-rw-r--r--src/config.rs90
-rw-r--r--src/window.rs187
5 files changed, 244 insertions, 58 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c42ccec..adcc849c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement the `hidden` escape sequence (`echo -e "\e[8mTEST"`)
- Add support for macOS systemwide dark mode
- Set the environment variable `COLORTERM="truecolor"` to advertise 24-bit color support
+- On macOS, there are two new values for the config option `window.decorations`:
+ - `transparent` - This makes the title bar transparent and allows the
+ viewport to extend to the top of the window.
+ - `buttonless` - Similar to transparent but also removed the buttons.
### Changed
@@ -23,6 +27,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Windows started as unfocused now show the hollow cursor if the setting is enabled
- Bracketed paste mode now filters escape sequences beginning with \x1b
+### Deprecated
+
+- The config option `window.decorations` should now use `full` or `none` instead
+ of `true` or `false`, respectively.
+
## Version 0.2.0
### Added
diff --git a/alacritty.yml b/alacritty.yml
index a0225f56..49a33737 100644
--- a/alacritty.yml
+++ b/alacritty.yml
@@ -30,8 +30,10 @@ window:
y: 2
# Window decorations
- # Setting this to false will result in window without borders and title bar.
- decorations: true
+ # Available values:
+ # - `full`: Window with borders and title bar.
+ # - `none`: Window without borders or title bar.
+ decorations: full
scrolling:
# How many lines of scrollback to keep,
diff --git a/alacritty_macos.yml b/alacritty_macos.yml
index 7834cc78..9c911e26 100644
--- a/alacritty_macos.yml
+++ b/alacritty_macos.yml
@@ -28,8 +28,14 @@ window:
y: 2
# Window decorations
- # Setting this to false will result in window without borders and title bar.
- decorations: true
+ # Available values:
+ # - `full`: Window with title bar and title bar buttons
+ # - `none`: Window without title bar, rounded corners, or drop shadow
+ # - `transparent`: Window with title bar with transparent background and title
+ # bar buttons
+ # - `buttonless`: Window with title bar with transparent background and no
+ # title bar buttons
+ decorations: full
scrolling:
# How many lines of scrollback to keep,
diff --git a/src/config.rs b/src/config.rs
index 6fad09f9..58e282d2 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -248,6 +248,89 @@ impl Default for Alpha {
}
}
+#[derive(Debug, Copy, Clone)]
+pub enum Decorations {
+ Full,
+ Transparent,
+ Buttonless,
+ None,
+}
+
+impl Default for Decorations {
+ fn default() -> Decorations {
+ Decorations::Full
+ }
+}
+
+impl<'de> Deserialize<'de> for Decorations {
+ fn deserialize<D>(deserializer: D) -> ::std::result::Result<Decorations, D::Error>
+ where D: de::Deserializer<'de>
+ {
+
+ struct DecorationsVisitor;
+
+ impl<'de> Visitor<'de> for DecorationsVisitor {
+ type Value = Decorations;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("Some subset of full|transparent|buttonless|none")
+ }
+
+ fn visit_bool<E>(self, value: bool) -> ::std::result::Result<Decorations, E>
+ where E: de::Error
+ {
+ if value {
+ eprintln!("deprecated decorations boolean value, use one of default|transparent|buttonless|none instead; Falling back to \"full\"");
+ Ok(Decorations::Full)
+ } else {
+ eprintln!("deprecated decorations boolean value, use one of default|transparent|buttonless|none instead; Falling back to \"none\"");
+ Ok(Decorations::None)
+ }
+ }
+
+ #[cfg(target_os = "macos")]
+ fn visit_str<E>(self, value: &str) -> ::std::result::Result<Decorations, E>
+ where E: de::Error
+ {
+ match value {
+ "transparent" => Ok(Decorations::Transparent),
+ "buttonless" => Ok(Decorations::Buttonless),
+ "none" => Ok(Decorations::None),
+ "full" => Ok(Decorations::Full),
+ _ => {
+ eprintln!("invalid decorations value: {}; Using default value", value);
+ Ok(Decorations::Full)
+ }
+ }
+ }
+
+ #[cfg(not(target_os = "macos"))]
+ fn visit_str<E>(self, value: &str) -> ::std::result::Result<Decorations, E>
+ where E: de::Error
+ {
+ match value {
+ "none" => Ok(Decorations::None),
+ "full" => Ok(Decorations::Full),
+ "transparent" => {
+ eprintln!("macos-only decorations value: {}; Using default value", value);
+ Ok(Decorations::Full)
+ },
+ "buttonless" => {
+ eprintln!("macos-only decorations value: {}; Using default value", value);
+ Ok(Decorations::Full)
+ }
+ _ => {
+ eprintln!("invalid decorations value: {}; Using default value", value);
+ Ok(Decorations::Full)
+ }
+ }
+ }
+ }
+
+ deserializer.deserialize_str(DecorationsVisitor)
+ }
+}
+
#[derive(Debug, Copy, Clone, Deserialize)]
pub struct WindowConfig {
/// Initial dimensions
@@ -259,8 +342,7 @@ pub struct WindowConfig {
padding: Delta<u8>,
/// Draw the window with title bar / borders
- #[serde(default, deserialize_with = "failure_default")]
- decorations: bool,
+ decorations: Decorations,
}
fn default_padding() -> Delta<u8> {
@@ -280,7 +362,7 @@ fn deserialize_padding<'a, D>(deserializer: D) -> ::std::result::Result<Delta<u8
}
impl WindowConfig {
- pub fn decorations(&self) -> bool {
+ pub fn decorations(&self) -> Decorations {
self.decorations
}
}
@@ -290,7 +372,7 @@ impl Default for WindowConfig {
WindowConfig{
dimensions: Default::default(),
padding: default_padding(),
- decorations: true,
+ decorations: Default::default(),
}
}
}
diff --git a/src/window.rs b/src/window.rs
index ede29716..eac4c014 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -16,14 +16,16 @@ use std::fmt::{self, Display};
use std::ops::Deref;
use gl;
-use glutin::{self, ContextBuilder, ControlFlow, CursorState, Event, EventsLoop,
- MouseCursor as GlutinMouseCursor, WindowBuilder};
use glutin::GlContext;
+use glutin::{
+ self, ContextBuilder, ControlFlow, CursorState, Event, EventsLoop,
+ MouseCursor as GlutinMouseCursor, WindowBuilder,
+};
use MouseCursor;
use cli::Options;
-use config::WindowConfig;
+use config::{Decorations, WindowConfig};
/// Default text for the window's title bar, if not overriden.
///
@@ -119,7 +121,7 @@ impl ToPoints for Size<Pixels<u32>> {
Size {
width: Points(width_pts),
- height: Points(height_pts)
+ height: Points(height_pts),
}
}
}
@@ -147,7 +149,6 @@ macro_rules! deref_newtype {
deref_newtype! { Points<T>, Pixels<T> }
-
impl<T: Display> Display for Pixels<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}px", self.0)
@@ -179,12 +180,8 @@ impl ::std::error::Error for Error {
impl Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
- Error::ContextCreation(ref err) => {
- write!(f, "Error creating GL context; {}", err)
- },
- Error::Context(ref err) => {
- write!(f, "Error operating on render context; {}", err)
- },
+ Error::ContextCreation(ref err) => write!(f, "Error creating GL context; {}", err),
+ Error::Context(ref err) => write!(f, "Error operating on render context; {}", err),
}
}
}
@@ -206,9 +203,7 @@ fn create_gl_window(
event_loop: &EventsLoop,
srgb: bool,
) -> ::std::result::Result<glutin::GlWindow, glutin::CreationError> {
- let context = ContextBuilder::new()
- .with_srgb(srgb)
- .with_vsync(true);
+ let context = ContextBuilder::new().with_srgb(srgb).with_vsync(true);
::glutin::GlWindow::new(window, context, event_loop)
}
@@ -216,19 +211,12 @@ impl Window {
/// Create a new window
///
/// This creates a window and fully initializes a window.
- pub fn new(
- options: &Options,
- window_config: &WindowConfig,
- ) -> Result<Window> {
+ pub fn new(options: &Options, window_config: &WindowConfig) -> Result<Window> {
let event_loop = EventsLoop::new();
let title = options.title.as_ref().map_or(DEFAULT_TITLE, |t| t);
let class = options.class.as_ref().map_or(DEFAULT_CLASS, |c| c);
- let window_builder = WindowBuilder::new()
- .with_title(title)
- .with_visibility(false)
- .with_transparency(true)
- .with_decorations(window_config.decorations());
+ let window_builder = Window::get_platform_window(title, window_config);
let window_builder = Window::platform_builder_ext(window_builder, &class);
let window = create_gl_window(window_builder.clone(), &event_loop, false)
.or_else(|_| create_gl_window(window_builder, &event_loop, true))?;
@@ -268,9 +256,10 @@ impl Window {
}
pub fn inner_size_pixels(&self) -> Option<Size<Pixels<u32>>> {
- self.window
- .get_inner_size()
- .map(|(w, h)| Size { width: Pixels(w), height: Pixels(h) })
+ self.window.get_inner_size().map(|(w, h)| Size {
+ width: Pixels(w),
+ height: Pixels(h),
+ })
}
#[inline]
@@ -287,15 +276,14 @@ impl Window {
#[inline]
pub fn swap_buffers(&self) -> Result<()> {
- self.window
- .swap_buffers()
- .map_err(From::from)
+ self.window.swap_buffers().map_err(From::from)
}
/// Poll for any available events
#[inline]
pub fn poll_events<F>(&mut self, func: F)
- where F: FnMut(Event)
+ where
+ F: FnMut(Event),
{
self.event_loop.poll_events(func);
}
@@ -308,7 +296,8 @@ impl Window {
/// Block waiting for events
#[inline]
pub fn wait_events<F>(&mut self, func: F)
- where F: FnMut(Event) -> ControlFlow
+ where
+ F: FnMut(Event) -> ControlFlow,
{
self.event_loop.run_forever(func);
}
@@ -341,24 +330,95 @@ impl Window {
}
}
- #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
+ #[cfg(
+ any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "openbsd"
+ )
+ )]
fn platform_builder_ext(window_builder: WindowBuilder, wm_class: &str) -> WindowBuilder {
use glutin::os::unix::WindowBuilderExt;
window_builder.with_class(wm_class.to_owned(), "Alacritty".to_owned())
}
- #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
+ #[cfg(
+ not(
+ any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "openbsd"
+ )
+ )
+ )]
fn platform_builder_ext(window_builder: WindowBuilder, _: &str) -> WindowBuilder {
window_builder
}
- #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
+ #[cfg(not(target_os = "macos"))]
+ pub fn get_platform_window(title: &str, window_config: &WindowConfig) -> WindowBuilder {
+ let decorations = match window_config.decorations() {
+ Decorations::None => false,
+ _ => true,
+ };
+
+ WindowBuilder::new()
+ .with_title(title)
+ .with_visibility(false)
+ .with_transparency(true)
+ .with_decorations(decorations)
+ }
+
+ #[cfg(target_os = "macos")]
+ pub fn get_platform_window(title: &str, window_config: &WindowConfig) -> WindowBuilder {
+ use glutin::os::macos::WindowBuilderExt;
+
+ let window = WindowBuilder::new()
+ .with_title(title)
+ .with_visibility(false)
+ .with_transparency(true);
+
+ match window_config.decorations() {
+ Decorations::Full => window,
+ Decorations::Transparent => window
+ .with_title_hidden(true)
+ .with_titlebar_transparent(true)
+ .with_fullsize_content_view(true),
+ Decorations::Buttonless => window
+ .with_title_hidden(true)
+ .with_titlebar_buttons_hidden(true)
+ .with_titlebar_transparent(true)
+ .with_fullsize_content_view(true),
+ Decorations::None => window
+ .with_titlebar_hidden(true),
+ }
+ }
+
+ #[cfg(
+ any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "openbsd"
+ )
+ )]
pub fn set_urgent(&self, is_urgent: bool) {
use glutin::os::unix::WindowExt;
self.window.set_urgent(is_urgent);
}
- #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
+ #[cfg(
+ not(
+ any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "openbsd"
+ )
+ )
+ )]
pub fn set_urgent(&self, _is_urgent: bool) {}
pub fn set_ime_spot(&self, x: i32, y: i32) {
@@ -371,7 +431,7 @@ impl Window {
match self.window.get_xlib_window() {
Some(xlib_window) => Some(xlib_window as usize),
- None => None
+ None => None,
}
}
@@ -390,17 +450,28 @@ pub trait OsExtensions {
fn run_os_extensions(&self) {}
}
-#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd")))]
-impl OsExtensions for Window { }
-
-#[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))]
+#[cfg(
+ not(
+ any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "openbsd"
+ )
+ )
+)]
+impl OsExtensions for Window {}
+
+#[cfg(
+ any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")
+)]
impl OsExtensions for Window {
fn run_os_extensions(&self) {
use glutin::os::unix::WindowExt;
- use x11_dl::xlib::{self, XA_CARDINAL, PropModeReplace};
- use std::ffi::{CStr};
- use std::ptr;
use libc::getpid;
+ use std::ffi::CStr;
+ use std::ptr;
+ use x11_dl::xlib::{self, PropModeReplace, XA_CARDINAL};
let xlib_display = self.window.get_xlib_display();
let xlib_window = self.window.get_xlib_window();
@@ -414,17 +485,32 @@ impl OsExtensions for Window {
let atom = (xlib.XInternAtom)(xlib_display as *mut _, _net_wm_pid.as_ptr(), 0);
let pid = getpid();
- (xlib.XChangeProperty)(xlib_display as _, xlib_window as _, atom,
- XA_CARDINAL, 32, PropModeReplace, &pid as *const i32 as *const u8, 1);
-
+ (xlib.XChangeProperty)(
+ xlib_display as _,
+ xlib_window as _,
+ atom,
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ &pid as *const i32 as *const u8,
+ 1,
+ );
}
// Although this call doesn't actually pass any data, it does cause
// WM_CLIENT_MACHINE to be set. WM_CLIENT_MACHINE MUST be set if _NET_WM_PID is set
// (which we do above).
unsafe {
- (xlib.XSetWMProperties)(xlib_display as _, xlib_window as _, ptr::null_mut(),
- ptr::null_mut(), ptr::null_mut(), 0, ptr::null_mut(), ptr::null_mut(),
- ptr::null_mut());
+ (xlib.XSetWMProperties)(
+ xlib_display as _,
+ xlib_window as _,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ 0,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ );
}
}
}
@@ -447,6 +533,7 @@ pub trait SetInnerSize<T> {
impl SetInnerSize<Pixels<u32>> for Window {
fn set_inner_size<T: ToPoints>(&mut self, size: &T) {
let size = size.to_points(self.hidpi_factor());
- self.window.set_inner_size(*size.width as _, *size.height as _);
+ self.window
+ .set_inner_size(*size.width as _, *size.height as _);
}
}