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