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}