1
0
Fork 0
forked from wry/wry

config: clean up and document theming

This commit is contained in:
Julian Orth 2022-05-15 20:10:04 +02:00
parent 4780315f50
commit 6916f03e94
17 changed files with 745 additions and 285 deletions

View file

@ -13,7 +13,7 @@ use {
},
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
keyboard::keymap::Keymap,
theme::Color,
theme::{colors::Colorable, sized::Resizable, Color},
Axis, Command, Direction, LogLevel, ModifiedKeySym, PciId, Timer, Workspace,
},
std::{
@ -149,7 +149,7 @@ pub unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize
}
macro_rules! get_response {
($res:expr, $def:expr, $ty:ident, $($field:ident),+) => {
($res:expr, $def:expr, $ty:ident { $($field:ident),+ }) => {
let ($($field,)+) = match $res {
Response::$ty { $($field,)+ } => ($($field,)+),
_ => {
@ -231,19 +231,19 @@ impl Client {
pub fn seats(&self) -> Vec<Seat> {
let res = self.send_with_response(&ClientMessage::GetSeats);
get_response!(res, vec![], GetSeats, seats);
get_response!(res, vec![], GetSeats { seats });
seats
}
pub fn mono(&self, seat: Seat) -> bool {
let res = self.send_with_response(&ClientMessage::GetMono { seat });
get_response!(res, false, GetMono, mono);
get_response!(res, false, GetMono { mono });
mono
}
pub fn get_timer(&self, name: &str) -> Timer {
let res = self.send_with_response(&ClientMessage::GetTimer { name });
get_response!(res, Timer(0), GetTimer, timer);
get_response!(res, Timer(0), GetTimer { timer });
timer
}
@ -270,13 +270,13 @@ impl Client {
pub fn get_workspace(&self, name: &str) -> Workspace {
let res = self.send_with_response(&ClientMessage::GetWorkspace { name });
get_response!(res, Workspace(0), GetWorkspace, workspace);
get_response!(res, Workspace(0), GetWorkspace { workspace });
workspace
}
pub fn get_connector(&self, ty: ConnectorType, idx: u32) -> Connector {
let res = self.send_with_response(&ClientMessage::GetConnector { ty, idx });
get_response!(res, Connector(0), GetConnector, connector);
get_response!(res, Connector(0), GetConnector { connector });
connector
}
@ -290,7 +290,7 @@ impl Client {
pub fn split(&self, seat: Seat) -> Axis {
let res = self.send_with_response(&ClientMessage::GetSplit { seat });
get_response!(res, Axis::Horizontal, GetSplit, axis);
get_response!(res, Axis::Horizontal, GetSplit { axis });
axis
}
@ -300,48 +300,64 @@ impl Client {
pub fn get_fullscreen(&self, seat: Seat) -> bool {
let res = self.send_with_response(&ClientMessage::GetFullscreen { seat });
get_response!(res, false, GetFullscreen, fullscreen);
get_response!(res, false, GetFullscreen { fullscreen });
fullscreen
}
pub fn reset_font(&self) {
self.send(&ClientMessage::ResetFont);
}
pub fn set_font(&self, font: &str) {
self.send(&ClientMessage::SetFont { font });
}
pub fn get_font(&self) -> String {
let res = self.send_with_response(&ClientMessage::GetFont);
get_response!(res, String::new(), GetFont { font });
font
}
pub fn get_floating(&self, seat: Seat) -> bool {
let res = self.send_with_response(&ClientMessage::GetFloating { seat });
get_response!(res, false, GetFloating { floating });
floating
}
pub fn set_floating(&self, seat: Seat, floating: bool) {
self.send(&ClientMessage::SetFloating { seat, floating });
}
pub fn toggle_floating(&self, seat: Seat) {
self.send(&ClientMessage::ToggleFloating { seat });
self.set_floating(seat, !self.get_floating(seat));
}
pub fn set_title_color(&self, color: Color) {
self.send(&ClientMessage::SetTitleColor { color });
pub fn reset_colors(&self) {
self.send(&ClientMessage::ResetColors);
}
pub fn set_border_color(&self, color: Color) {
self.send(&ClientMessage::SetBorderColor { color });
pub fn reset_sizes(&self) {
self.send(&ClientMessage::ResetSizes);
}
pub fn set_title_underline_color(&self, color: Color) {
self.send(&ClientMessage::SetTitleUnderlineColor { color });
pub fn get_color(&self, colorable: Colorable) -> Color {
let res = self.send_with_response(&ClientMessage::GetColor { colorable });
get_response!(res, Color::BLACK, GetColor { color });
color
}
pub fn set_background_color(&self, color: Color) {
self.send(&ClientMessage::SetBackgroundColor { color });
pub fn set_color(&self, colorable: Colorable, color: Color) {
self.send(&ClientMessage::SetColor { colorable, color });
}
pub fn get_title_height(&self) -> i32 {
let res = self.send_with_response(&ClientMessage::GetTitleHeight);
get_response!(res, 0, GetTitleHeight, height);
height
pub fn get_size(&self, sized: Resizable) -> i32 {
let res = self.send_with_response(&ClientMessage::GetSize { sized });
get_response!(res, 0, GetSize { size });
size
}
pub fn get_border_width(&self) -> i32 {
let res = self.send_with_response(&ClientMessage::GetBorderWidth);
get_response!(res, 0, GetBorderWidth, width);
width
}
pub fn set_title_height(&self, height: i32) {
self.send(&ClientMessage::SetTitleHeight { height })
}
pub fn set_border_width(&self, width: i32) {
self.send(&ClientMessage::SetBorderWidth { width })
pub fn set_size(&self, sized: Resizable, size: i32) {
self.send(&ClientMessage::SetSize { sized, size })
}
pub fn set_mono(&self, seat: Seat, mono: bool) {
@ -374,13 +390,13 @@ impl Client {
pub fn get_seat(&self, name: &str) -> Seat {
let res = self.send_with_response(&ClientMessage::GetSeat { name });
get_response!(res, Seat(0), GetSeat, seat);
get_response!(res, Seat(0), GetSeat { seat });
seat
}
pub fn get_input_devices(&self, seat: Option<Seat>) -> Vec<InputDevice> {
let res = self.send_with_response(&ClientMessage::GetInputDevices { seat });
get_response!(res, vec!(), GetInputDevices, devices);
get_response!(res, vec!(), GetInputDevices { devices });
devices
}
@ -406,43 +422,43 @@ impl Client {
pub fn device_connectors(&self, device: DrmDevice) -> Vec<Connector> {
let res = self.send_with_response(&ClientMessage::GetDeviceConnectors { device });
get_response!(res, vec![], GetDeviceConnectors, connectors);
get_response!(res, vec![], GetDeviceConnectors { connectors });
connectors
}
pub fn drm_device_syspath(&self, device: DrmDevice) -> String {
let res = self.send_with_response(&ClientMessage::GetDrmDeviceSyspath { device });
get_response!(res, String::new(), GetDrmDeviceSyspath, syspath);
get_response!(res, String::new(), GetDrmDeviceSyspath { syspath });
syspath
}
pub fn drm_device_vendor(&self, device: DrmDevice) -> String {
let res = self.send_with_response(&ClientMessage::GetDrmDeviceVendor { device });
get_response!(res, String::new(), GetDrmDeviceVendor, vendor);
get_response!(res, String::new(), GetDrmDeviceVendor { vendor });
vendor
}
pub fn drm_device_model(&self, device: DrmDevice) -> String {
let res = self.send_with_response(&ClientMessage::GetDrmDeviceModel { device });
get_response!(res, String::new(), GetDrmDeviceModel, model);
get_response!(res, String::new(), GetDrmDeviceModel { model });
model
}
pub fn drm_device_pci_id(&self, device: DrmDevice) -> PciId {
let res = self.send_with_response(&ClientMessage::GetDrmDevicePciId { device });
get_response!(res, Default::default(), GetDrmDevicePciId, pci_id);
get_response!(res, Default::default(), GetDrmDevicePciId { pci_id });
pci_id
}
pub fn connector_connected(&self, connector: Connector) -> bool {
let res = self.send_with_response(&ClientMessage::ConnectorConnected { connector });
get_response!(res, false, ConnectorConnected, connected);
get_response!(res, false, ConnectorConnected { connected });
connected
}
pub fn connector_type(&self, connector: Connector) -> ConnectorType {
let res = self.send_with_response(&ClientMessage::ConnectorType { connector });
get_response!(res, CON_UNKNOWN, ConnectorType, ty);
get_response!(res, CON_UNKNOWN, ConnectorType { ty });
ty
}
@ -451,10 +467,11 @@ impl Client {
get_response!(
res,
Mode::zeroed(),
ConnectorMode,
width,
height,
refresh_millihz
ConnectorMode {
width,
height,
refresh_millihz
}
);
Mode {
width,
@ -465,7 +482,7 @@ impl Client {
pub fn drm_devices(&self) -> Vec<DrmDevice> {
let res = self.send_with_response(&ClientMessage::GetDrmDevices);
get_response!(res, vec![], GetDrmDevices, devices);
get_response!(res, vec![], GetDrmDevices { devices });
devices
}
@ -514,13 +531,13 @@ impl Client {
pub fn device_name(&self, device: InputDevice) -> String {
let res = self.send_with_response(&ClientMessage::GetDeviceName { device });
get_response!(res, String::new(), GetDeviceName, name);
get_response!(res, String::new(), GetDeviceName { name });
name
}
pub fn has_capability(&self, device: InputDevice, cap: Capability) -> bool {
let res = self.send_with_response(&ClientMessage::HasCapability { device, cap });
get_response!(res, false, HasCapability, has);
get_response!(res, false, HasCapability { has });
has
}
@ -534,13 +551,13 @@ impl Client {
pub fn seat_get_repeat_rate(&self, seat: Seat) -> (i32, i32) {
let res = self.send_with_response(&ClientMessage::SeatGetRepeatRate { seat });
get_response!(res, (25, 250), GetRepeatRate, rate, delay);
get_response!(res, (25, 250), GetRepeatRate { rate, delay });
(rate, delay)
}
pub fn parse_keymap(&self, keymap: &str) -> Keymap {
let res = self.send_with_response(&ClientMessage::ParseKeymap { keymap });
get_response!(res, Keymap(0), ParseKeymap, keymap);
get_response!(res, Keymap(0), ParseKeymap { keymap });
keymap
}

View file

@ -3,7 +3,7 @@ use {
drm::{connector_type::ConnectorType, Connector, DrmDevice},
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
keyboard::{keymap::Keymap, mods::Modifiers, syms::KeySym},
theme::Color,
theme::{colors::Colorable, sized::Resizable, Color},
Axis, Direction, LogLevel, PciId, Timer, Workspace,
},
bincode::{BorrowDecode, Decode, Encode},
@ -56,6 +56,11 @@ pub enum ServerMessage {
#[derive(Encode, BorrowDecode, Debug)]
pub enum ClientMessage<'a> {
Reload,
Quit,
SwitchTo {
vtnr: u32,
},
Log {
level: LogLevel,
msg: &'a str,
@ -65,10 +70,6 @@ pub enum ClientMessage<'a> {
GetSeat {
name: &'a str,
},
Quit,
SwitchTo {
vtnr: u32,
},
SetSeat {
device: InputDevice,
seat: Seat,
@ -139,24 +140,20 @@ pub enum ClientMessage<'a> {
kb: InputDevice,
grab: bool,
},
GetTitleHeight,
GetBorderWidth,
SetTitleHeight {
height: i32,
ResetSizes,
GetSize {
sized: Resizable,
},
SetBorderWidth {
width: i32,
SetSize {
sized: Resizable,
size: i32,
},
SetTitleColor {
color: Color,
ResetColors,
GetColor {
colorable: Colorable,
},
SetTitleUnderlineColor {
color: Color,
},
SetBorderColor {
color: Color,
},
SetBackgroundColor {
SetColor {
colorable: Colorable,
color: Color,
},
CreateSplit {
@ -169,9 +166,13 @@ pub enum ClientMessage<'a> {
FocusParent {
seat: Seat,
},
ToggleFloating {
GetFloating {
seat: Seat,
},
SetFloating {
seat: Seat,
floating: bool,
},
HasCapability {
device: InputDevice,
cap: Capability,
@ -246,7 +247,6 @@ pub enum ClientMessage<'a> {
GetFullscreen {
seat: Seat,
},
Reload,
GetDeviceConnectors {
device: DrmDevice,
},
@ -263,6 +263,11 @@ pub enum ClientMessage<'a> {
GetDrmDevicePciId {
device: DrmDevice,
},
ResetFont,
GetFont,
SetFont {
font: &'a str,
},
}
#[derive(Encode, Decode, Debug)]
@ -290,11 +295,8 @@ pub enum Response {
GetInputDevices {
devices: Vec<InputDevice>,
},
GetTitleHeight {
height: i32,
},
GetBorderWidth {
width: i32,
GetSize {
size: i32,
},
HasCapability {
has: bool,
@ -343,6 +345,15 @@ pub enum Response {
GetDrmDevicePciId {
pci_id: PciId,
},
GetFloating {
floating: bool,
},
GetColor {
color: Color,
},
GetFont {
font: String,
},
}
#[derive(Encode, Decode, Debug)]

View file

@ -123,6 +123,14 @@ impl Seat {
get!().close(self);
}
pub fn get_floating(self) -> bool {
get!().get_floating(self)
}
pub fn set_floating(self, floating: bool) {
get!().set_floating(self, floating);
}
pub fn toggle_floating(self) {
get!().toggle_floating(self);
}

View file

@ -1,45 +1,290 @@
use bincode::{BorrowDecode, Encode};
//! Knobs for changing the look of the compositor.
#[derive(Encode, BorrowDecode, Debug)]
use bincode::{Decode, Encode};
/// A color.
///
/// When specifying RGBA values of a color, the RGB values can either be specified
/// *straight* or *premultiplied*. Premultiplied means that the RGB values have already
/// been multiplied by the alpha value.
///
/// Given a color, to reduce its opacity by half,
///
/// - if you're working with premultiplied values, you would multiply each component by `0.5`;
/// - if you're working with straight values, you would multiply only the alpha component by `0.5`.
///
/// When using hexadecimal notation, `#RRGGBBAA`, the RGB values are usually straight.
// values are stored premultiplied
#[derive(Encode, Decode, Debug)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
r: f32,
g: f32,
b: f32,
a: f32,
}
pub fn set_title_color(color: Color) {
get!().set_title_color(color)
fn to_f32(c: u8) -> f32 {
c as f32 / 255f32
}
pub fn set_title_underline_color(color: Color) {
get!().set_title_underline_color(color)
fn to_u8(c: f32) -> u8 {
(c * 255f32) as u8
}
pub fn set_border_color(color: Color) {
get!().set_border_color(color)
fn validate_f32(f: f32) -> bool {
f.is_normal() && f >= 0.0 && f <= 1.0
}
pub fn set_background_color(color: Color) {
get!().set_background_color(color)
fn validate_f32_all(f: [f32; 4]) -> bool {
if !f.into_iter().all(validate_f32) {
log::warn!(
"f32 values {:?} are not in the valid color range. Using solid black instead",
f
);
return false;
}
true
}
pub fn get_title_height() -> i32 {
let mut res = 0;
(|| res = get!().get_title_height())();
res
impl Color {
/// Solid black.
pub const BLACK: Self = Self {
r: 0.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
/// Creates a new color from `u8` RGB values.
pub fn new(r: u8, g: u8, b: u8) -> Self {
Self {
r: to_f32(r),
g: to_f32(g),
b: to_f32(b),
a: 1.0,
}
}
/// Creates a new color from straight `u8` RGBA values.
pub fn new_straight(r: u8, g: u8, b: u8, a: u8) -> Self {
Self::new_f32_straight(to_f32(r), to_f32(g), to_f32(b), to_f32(a))
}
/// Creates a new color from premultiplied `f32` RGBA values.
pub fn new_f32_premultiplied(r: f32, g: f32, b: f32, a: f32) -> Self {
if validate_f32_all([r, g, b, a]) {
Self::BLACK
} else if r > a || g > a || b > a {
log::warn!("f32 values {:?} are not valid valid for a premultiplied color. Using solid black instead.", [r, g, b, a]);
Self::BLACK
} else {
Self { r, g, b, a }
}
}
/// Creates a new color from straight `f32` RGBA values.
pub fn new_f32_straight(r: f32, g: f32, b: f32, a: f32) -> Self {
if validate_f32_all([r, g, b, a]) {
Self::BLACK
} else {
Self {
r: r * a,
g: g * a,
b: b * a,
a,
}
}
}
/// Creates a new color from `f32` RGB values.
pub fn new_f32(r: f32, g: f32, b: f32) -> Self {
Self { r, g, b, a: 1.0 }
}
/// Converts the color to its premultiplied `f32` RGBA values.
pub fn to_f32_premultiplied(&self) -> [f32; 4] {
[self.r, self.g, self.b, self.a]
}
/// Converts the color to its straight `f32` RGBA values.
pub fn to_f32_straight(&self) -> [f32; 4] {
if self.a == 0.0 {
[0.0, 0.0, 0.0, 0.0]
} else {
let a = self.a;
[self.r / a, self.g / a, self.b / a, a]
}
}
/// Converts the color to its straight `u8` RGBA values.
pub fn to_u8_straight(&self) -> [u8; 4] {
let [r, g, b, a] = self.to_f32_straight();
[to_u8(r), to_u8(g), to_u8(b), to_u8(a)]
}
}
pub fn get_border_width() -> i32 {
let mut res = 0;
(|| res = get!().get_border_width())();
res
/// Resets all sizes to their defaults.
pub fn reset_sizes() {
get!().reset_sizes();
}
pub fn set_title_height(height: i32) {
get!().set_title_height(height)
/// Resets all colors to their defaults.
pub fn reset_colors() {
get!().reset_colors();
}
pub fn set_border_width(width: i32) {
get!().set_border_width(width)
/// Returns the current font.
pub fn get_font() -> String {
get!().get_font()
}
/// Sets the font.
///
/// Default: `monospace 8`.
///
/// The font name should be specified in [pango][pango] syntax.
///
/// [pango]: https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html
pub fn set_font(font: &str) {
get!().set_font(font)
}
/// Resets the font to the default.
///
/// Currently the default is `monospace 8`.
pub fn reset_font() {
get!().reset_font()
}
/// Tools for customizing the colors of the desktop.
pub mod colors {
use {
crate::theme::Color,
bincode::{Decode, Encode},
};
/// An element of the GUI whose color can be changed.
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct Colorable(#[doc(hidden)] pub u32);
impl Colorable {
/// Sets the color to an RGB value.
pub fn set(self, r: u8, g: u8, b: u8) {
let color = Color::new(r, g, b);
get!().set_color(self, color);
}
/// Sets the color to a `Color` that might contain an alpha component.
pub fn set_color(self, color: Color) {
get!().set_color(self, color);
}
/// Gets the current color.
pub fn get(self) -> Color {
get!(Color::BLACK).get_color(self)
}
}
macro_rules! colors {
($($(#[$attr:meta])* const $n:expr => $name:ident,)*) => {
$(
$(#[$attr])*
pub const $name: Colorable = Colorable($n);
)*
}
}
colors! {
/// The title background color of an unfocused window.
///
/// Default: `#222222`.
const 01 => UNFOCUSED_TITLE_BACKGROUND_COLOR,
/// The title background color of a focused window.
///
/// Default: `#285577`.
const 02 => FOCUSED_TITLE_BACKGROUND_COLOR,
/// The title background color of an unfocused window that was the last focused
/// window in its container.
///
/// Default: `#5f676a`.
const 03 => FOCUSED_INACTIVE_TITLE_BACKGROUND_COLOR,
/// The background color of the desktop.
///
/// Default: `#001019`.
///
/// You can use an application such as [swaybg][swaybg] to further customize the background.
///
/// [swaybg]: https://github.com/swaywm/swaybg
const 04 => BACKGROUND_COLOR,
/// The background color of the bar.
///
/// Default: `#000000`.
const 05 => BAR_BACKGROUND_COLOR,
/// The color of the 1px separator below window titles.
///
/// Default: `#333333`.
const 06 => SEPARATOR_COLOR,
/// The color of the border between windows.
///
/// Default: `#3f474a`.
const 07 => BORDER_COLOR,
/// The title text color of an unfocused window.
///
/// Default: `#888888`.
const 08 => UNFOCUSED_TITLE_TEXT_COLOR,
/// The title text color of a focused window.
///
/// Default: `#ffffff`.
const 09 => FOCUSED_TITLE_TEXT_COLOR,
/// The title text color of an unfocused window that was the last focused
/// window in its container.
///
/// Default: `#ffffff`.
const 10 => FOCUSED_INACTIVE_TITLE_TEXT_COLOR,
/// The color of the status text in the bar.
///
/// Default: `#ffffff`.
const 11 => BAR_STATUS_TEXT_COLOR,
}
}
/// Tools for customizing the sizes of GUI elements.
pub mod sized {
use bincode::{Decode, Encode};
/// An element of the GUI whose size can be changed.
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct Resizable(#[doc(hidden)] pub u32);
impl Resizable {
/// Gets the current size.
pub fn get(self) -> i32 {
get!(0).get_size(self)
}
/// Sets the size.
pub fn set(self, size: i32) {
get!().set_size(self, size)
}
}
macro_rules! sizes {
($($(#[$attr:meta])* const $n:expr => $name:ident,)*) => {
$(
$(#[$attr])*
pub const $name: Resizable = Resizable($n);
)*
}
}
sizes! {
/// The height of window titles.
///
/// Default: 17
const 01 => TITLE_HEIGHT,
/// The width of borders between windows.
///
/// Default: 4
const 02 => BORDER_WIDTH,
}
}