penrose_ui/
lib.rs

1//! # Penrose-ui: a bare bones toolkit for adding UI elements to Penrose
2//!
3//! ## A note on the intended purpose of this crate
4//! Penrose-ui is not intended as a general purpose UI library. It is incredibly minimal in the
5//! functionality it provides and is primarily designed to provide a built-in status bar for the
6//! [penrose][0] tiling window manager library. While it should be possible to make use of this
7//! crate for writing UIs without integrating with penrose, that is certainly not the intended
8//! use case and is not fully supported.
9//!
10//! ## Getting started
11//! The main functionality of this crate is provided through the [`Draw`] nad [`Context`] structs
12//! which allow for simple graphics rendering backed by the xlib and fontconfig libraries.
13//!
14//! ## A note on the use of unsafe code
15//! Given the aims of this crate and the desire to pull in as few dependencies as possible, it
16//! makes heavy use of `unsafe` to wrap C FFI calls. Please make sure that you read the available
17//! documentation and `SAFETY` comments in the source code to understand what is happening under
18//! the hood if you have any concerns about this.
19//!
20//! [0]: https://github.com/sminez/penrose
21#![warn(
22    clippy::complexity,
23    clippy::correctness,
24    clippy::style,
25    clippy::undocumented_unsafe_blocks,
26    future_incompatible,
27    missing_debug_implementations,
28    missing_docs,
29    rust_2018_idioms,
30    rustdoc::all
31)]
32#![doc(
33    html_logo_url = "https://raw.githubusercontent.com/sminez/penrose/develop/icon.svg",
34    issue_tracker_base_url = "https://github.com/sminez/penrose/issues/"
35)]
36
37use penrose::{Color, WinId, x::XConn};
38use std::ffi::NulError;
39
40pub mod bar;
41pub mod core;
42pub mod layout_viewer;
43
44pub use crate::core::{Context, Draw, TextStyle};
45pub use bar::{Position, StatusBar};
46
47use bar::widgets::{ActiveWindowName, CurrentLayout, RootWindowName, Workspaces};
48
49/// Error variants from penrose_ui library.
50#[derive(thiserror::Error, Debug)]
51pub enum Error {
52    /// Creation of a [`Color`] from a string hex code was invalid
53    #[error("Invalid Hex color code: {code}")]
54    InvalidHexColor {
55        /// The invalid string that was intended as a color hex code
56        code: String,
57    },
58
59    /// The specified character can not be rendered by any font on this system
60    #[error("Unable to find a fallback font for '{0}'")]
61    NoFallbackFontForChar(char),
62
63    /// A string being passed to underlying C APIs contained an internal null byte
64    #[error(transparent)]
65    NulError(#[from] NulError),
66
67    /// Unable to parse an integer from a provided string.
68    #[error(transparent)]
69    ParseInt(#[from] std::num::ParseIntError),
70
71    /// An error was returned from the [`XConn`] when interacting with the X server
72    #[error(transparent)]
73    Penrose(#[from] penrose::Error),
74
75    /// Unable to allocate a requested color
76    #[error("Unable to allocate the requested color using Xft")]
77    UnableToAllocateColor,
78
79    /// Unable to open a requested font
80    #[error("Unable to open '{0}' as a font using Xft")]
81    UnableToOpenFont(String),
82
83    /// Unable to open a font using an Xft font pattern
84    #[error("Unable to open font from FcPattern using Xft")]
85    UnableToOpenFontPattern,
86
87    /// Unable to parse an Xft font pattern
88    #[error("Unable to parse '{0}' as an Xft font patten")]
89    UnableToParseFontPattern(String),
90
91    /// An attempt was made to work with a surface for a window that was not initialised
92    /// by the [`Draw`] instance being used.
93    #[error("no surface for {id}")]
94    UnintialisedSurface {
95        /// The window id requested
96        id: WinId,
97    },
98}
99
100/// A Result where the error type is a penrose_ui [`Error`]
101pub type Result<T> = std::result::Result<T, Error>;
102
103/// Create a default dwm style status bar that displays content pulled from the
104/// WM_NAME property of the root window.
105pub fn status_bar<X: XConn>(
106    height: u32,
107    font: &str,
108    point_size: u8,
109    style: TextStyle,
110    highlight: impl Into<Color>,
111    empty_ws: impl Into<Color>,
112    position: Position,
113) -> Result<StatusBar<X>> {
114    let max_active_window_chars = 80;
115    let highlight = highlight.into();
116
117    StatusBar::try_new(
118        position,
119        height,
120        style.bg.unwrap_or_else(|| 0x000000.into()),
121        font,
122        point_size,
123        vec![
124            Box::new(Workspaces::new(style, highlight, empty_ws)),
125            Box::new(CurrentLayout::new(style)),
126            Box::new(ActiveWindowName::new(
127                max_active_window_chars,
128                TextStyle {
129                    bg: Some(highlight),
130                    padding: (6, 4),
131                    ..style
132                },
133                true,
134                false,
135            )),
136            Box::new(RootWindowName::new(
137                TextStyle {
138                    padding: (4, 2),
139                    ..style
140                },
141                false,
142                true,
143            )),
144        ],
145    )
146}