config: clean up and document theming
This commit is contained in:
parent
4780315f50
commit
6916f03e94
17 changed files with 745 additions and 285 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ use {
|
|||
config::ConfigProxy,
|
||||
ifs::wl_seat::{SeatId, WlSeatGlobal},
|
||||
state::{ConnectorData, DeviceHandlerData, DrmDevData, OutputData, State},
|
||||
tree::{ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase},
|
||||
theme::{Color, ThemeSized, DEFAULT_FONT},
|
||||
tree::{ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase, OutputNode},
|
||||
utils::{
|
||||
copyhashmap::CopyHashMap,
|
||||
debug_fn::debug_fn,
|
||||
|
|
@ -36,6 +37,7 @@ use {
|
|||
InputDevice, Seat,
|
||||
},
|
||||
keyboard::{keymap::Keymap, mods::Modifiers, syms::KeySym},
|
||||
theme::{colors::Colorable, sized::Resizable},
|
||||
Axis, Direction, LogLevel, Workspace,
|
||||
},
|
||||
libloading::Library,
|
||||
|
|
@ -742,18 +744,6 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_title_height(&self) {
|
||||
self.respond(Response::GetTitleHeight {
|
||||
height: self.state.theme.title_height.get(),
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_get_border_width(&self) {
|
||||
self.respond(Response::GetBorderWidth {
|
||||
width: self.state.theme.border_width.get(),
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_create_split(&self, seat: Seat, axis: Axis) -> Result<(), CphError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.create_split(axis.into());
|
||||
|
|
@ -775,15 +765,27 @@ impl ConfigProxyHandler {
|
|||
self.state.backend.get().switch_to(vtnr);
|
||||
}
|
||||
|
||||
fn handle_toggle_floating(&self, seat: Seat) -> Result<(), CphError> {
|
||||
fn handle_get_floating(&self, seat: Seat) -> Result<(), CphError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.toggle_floating();
|
||||
self.respond(Response::GetFloating {
|
||||
floating: seat.get_floating().unwrap_or(false),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_floating(&self, seat: Seat, floating: bool) -> Result<(), CphError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.set_floating(floating);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spaces_change(&self) {
|
||||
struct V;
|
||||
impl NodeVisitorBase for V {
|
||||
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
||||
node.on_spaces_changed();
|
||||
node.node_visit_children(self);
|
||||
}
|
||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||
node.on_spaces_changed();
|
||||
node.node_visit_children(self);
|
||||
|
|
@ -796,7 +798,7 @@ impl ConfigProxyHandler {
|
|||
self.state.root.clone().node_visit(&mut V);
|
||||
}
|
||||
|
||||
fn colors_change(&self) {
|
||||
fn colors_changed(&self) {
|
||||
struct V;
|
||||
impl NodeVisitorBase for V {
|
||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||
|
|
@ -811,45 +813,95 @@ impl ConfigProxyHandler {
|
|||
self.state.root.clone().node_visit(&mut V);
|
||||
}
|
||||
|
||||
fn handle_set_title_height(&self, height: i32) -> Result<(), CphError> {
|
||||
if height < 0 {
|
||||
return Err(CphError::NegativeTitleHeight(height));
|
||||
fn get_sized(&self, sized: Resizable) -> Result<ThemeSized, CphError> {
|
||||
use jay_config::theme::sized::*;
|
||||
let sized = match sized {
|
||||
TITLE_HEIGHT => ThemeSized::title_height,
|
||||
BORDER_WIDTH => ThemeSized::border_width,
|
||||
_ => return Err(CphError::UnknownSized(sized.0)),
|
||||
};
|
||||
Ok(sized)
|
||||
}
|
||||
|
||||
fn handle_get_size(&self, sized: Resizable) -> Result<(), CphError> {
|
||||
let sized = self.get_sized(sized)?;
|
||||
let size = sized.field(&self.state.theme).get();
|
||||
self.respond(Response::GetSize { size });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_size(&self, sized: Resizable, size: i32) -> Result<(), CphError> {
|
||||
let sized = self.get_sized(sized)?;
|
||||
if size < sized.min() {
|
||||
return Err(CphError::InvalidSize(size, sized));
|
||||
}
|
||||
if height > 1000 {
|
||||
return Err(CphError::ExcessiveTitleHeight(height));
|
||||
if size > sized.max() {
|
||||
return Err(CphError::InvalidSize(size, sized));
|
||||
}
|
||||
self.state.theme.title_height.set(height);
|
||||
sized.field(&self.state.theme).set(size);
|
||||
self.spaces_change();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_border_width(&self, width: i32) -> Result<(), CphError> {
|
||||
if width < 0 {
|
||||
return Err(CphError::NegativeBorderWidth(width));
|
||||
}
|
||||
if width > 1000 {
|
||||
return Err(CphError::ExcessiveBorderWidth(width));
|
||||
}
|
||||
self.state.theme.border_width.set(width);
|
||||
fn handle_reset_colors(&self) {
|
||||
self.state.theme.colors.reset();
|
||||
self.colors_changed();
|
||||
}
|
||||
|
||||
fn handle_reset_sizes(&self) {
|
||||
self.state.theme.sizes.reset();
|
||||
self.spaces_change();
|
||||
}
|
||||
|
||||
fn handle_reset_font(&self) {
|
||||
*self.state.theme.font.borrow_mut() = DEFAULT_FONT.to_string();
|
||||
}
|
||||
|
||||
fn handle_set_font(&self, font: &str) {
|
||||
*self.state.theme.font.borrow_mut() = font.to_string();
|
||||
}
|
||||
|
||||
fn handle_get_font(&self) {
|
||||
let font = self.state.theme.font.borrow_mut().clone();
|
||||
self.respond(Response::GetFont { font });
|
||||
}
|
||||
|
||||
fn get_color(&self, colorable: Colorable) -> Result<&Cell<Color>, CphError> {
|
||||
let colors = &self.state.theme.colors;
|
||||
use jay_config::theme::colors::*;
|
||||
let colorable = match colorable {
|
||||
UNFOCUSED_TITLE_BACKGROUND_COLOR => &colors.unfocused_title_background,
|
||||
FOCUSED_TITLE_BACKGROUND_COLOR => &colors.focused_title_background,
|
||||
FOCUSED_INACTIVE_TITLE_BACKGROUND_COLOR => &colors.focused_inactive_title_background,
|
||||
BACKGROUND_COLOR => &colors.background,
|
||||
BAR_BACKGROUND_COLOR => &colors.bar_background,
|
||||
SEPARATOR_COLOR => &colors.separator,
|
||||
BORDER_COLOR => &colors.border,
|
||||
UNFOCUSED_TITLE_TEXT_COLOR => &colors.unfocused_title_text,
|
||||
FOCUSED_TITLE_TEXT_COLOR => &colors.focused_title_text,
|
||||
FOCUSED_INACTIVE_TITLE_TEXT_COLOR => &colors.focused_inactive_title_text,
|
||||
BAR_STATUS_TEXT_COLOR => &colors.bar_text,
|
||||
_ => return Err(CphError::UnknownColor(colorable.0)),
|
||||
};
|
||||
Ok(colorable)
|
||||
}
|
||||
|
||||
fn handle_get_color(&self, colorable: Colorable) -> Result<(), CphError> {
|
||||
let color = self.get_color(colorable)?.get();
|
||||
let color =
|
||||
jay_config::theme::Color::new_f32_premultiplied(color.r, color.g, color.b, color.a);
|
||||
self.respond(Response::GetColor { color });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_title_color(&self, color: jay_config::theme::Color) {
|
||||
self.state.theme.title_color.set(color.into());
|
||||
self.colors_change();
|
||||
}
|
||||
|
||||
fn handle_set_border_color(&self, color: jay_config::theme::Color) {
|
||||
self.state.theme.border_color.set(color.into());
|
||||
}
|
||||
|
||||
fn handle_set_background_color(&self, color: jay_config::theme::Color) {
|
||||
self.state.theme.background_color.set(color.into());
|
||||
}
|
||||
|
||||
fn handle_set_title_underline_color(&self, color: jay_config::theme::Color) {
|
||||
self.state.theme.underline_color.set(color.into());
|
||||
fn handle_set_color(
|
||||
&self,
|
||||
colorable: Colorable,
|
||||
color: jay_config::theme::Color,
|
||||
) -> Result<(), CphError> {
|
||||
self.get_color(colorable)?.set(color.into());
|
||||
self.colors_changed();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_request(self: &Rc<Self>, msg: &[u8]) {
|
||||
|
|
@ -914,29 +966,24 @@ impl ConfigProxyHandler {
|
|||
self.handle_run(prog, args, env).wrn("run")?
|
||||
}
|
||||
ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab).wrn("grab")?,
|
||||
ClientMessage::SetTitleHeight { height } => self
|
||||
.handle_set_title_height(height)
|
||||
.wrn("set_title_height")?,
|
||||
ClientMessage::SetBorderWidth { width } => self
|
||||
.handle_set_border_width(width)
|
||||
.wrn("set_bordre_width")?,
|
||||
ClientMessage::SetTitleColor { color } => self.handle_set_title_color(color),
|
||||
ClientMessage::SetTitleUnderlineColor { color } => {
|
||||
self.handle_set_title_underline_color(color)
|
||||
ClientMessage::SetColor { colorable, color } => {
|
||||
self.handle_set_color(colorable, color).wrn("set_color")?
|
||||
}
|
||||
ClientMessage::GetColor { colorable } => {
|
||||
self.handle_get_color(colorable).wrn("get_color")?
|
||||
}
|
||||
ClientMessage::SetBorderColor { color } => self.handle_set_border_color(color),
|
||||
ClientMessage::SetBackgroundColor { color } => self.handle_set_background_color(color),
|
||||
ClientMessage::GetTitleHeight => self.handle_get_title_height(),
|
||||
ClientMessage::GetBorderWidth => self.handle_get_border_width(),
|
||||
ClientMessage::CreateSplit { seat, axis } => {
|
||||
self.handle_create_split(seat, axis).wrn("create_split")?
|
||||
}
|
||||
ClientMessage::FocusParent { seat } => {
|
||||
self.handle_focus_parent(seat).wrn("focus_parent")?
|
||||
}
|
||||
ClientMessage::ToggleFloating { seat } => {
|
||||
self.handle_toggle_floating(seat).wrn("toggle_floating")?
|
||||
ClientMessage::GetFloating { seat } => {
|
||||
self.handle_get_floating(seat).wrn("get_floating")?
|
||||
}
|
||||
ClientMessage::SetFloating { seat, floating } => self
|
||||
.handle_set_floating(seat, floating)
|
||||
.wrn("set_floating")?,
|
||||
ClientMessage::Quit => self.handle_quit(),
|
||||
ClientMessage::SwitchTo { vtnr } => self.handle_switch_to(vtnr),
|
||||
ClientMessage::HasCapability { device, cap } => self
|
||||
|
|
@ -1019,6 +1066,15 @@ impl ConfigProxyHandler {
|
|||
ClientMessage::GetDrmDevicePciId { device } => self
|
||||
.handle_get_drm_device_pci_id(device)
|
||||
.wrn("get_drm_device_pci_id")?,
|
||||
ClientMessage::ResetColors => self.handle_reset_colors(),
|
||||
ClientMessage::ResetSizes => self.handle_reset_sizes(),
|
||||
ClientMessage::GetSize { sized } => self.handle_get_size(sized).wrn("get_size")?,
|
||||
ClientMessage::SetSize { sized, size } => {
|
||||
self.handle_set_size(sized, size).wrn("set_size")?
|
||||
}
|
||||
ClientMessage::ResetFont => self.handle_reset_font(),
|
||||
ClientMessage::GetFont => self.handle_get_font(),
|
||||
ClientMessage::SetFont { font } => self.handle_set_font(font),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1030,14 +1086,8 @@ enum CphError {
|
|||
UnknownAccelProfile(AccelProfile),
|
||||
#[error("Queried unknown capability: {}", (.0).0)]
|
||||
UnknownCapability(Capability),
|
||||
#[error("The height {0} is negative")]
|
||||
NegativeTitleHeight(i32),
|
||||
#[error("The height {0} is larger than the maximum 1000")]
|
||||
ExcessiveTitleHeight(i32),
|
||||
#[error("The width {0} is negative")]
|
||||
NegativeBorderWidth(i32),
|
||||
#[error("The width {0} is larger than the maximum 1000")]
|
||||
ExcessiveBorderWidth(i32),
|
||||
#[error("The sized {0} is outside the valid range [{}, {}] for component {}", .1.min(), .1.max(), .1.name())]
|
||||
InvalidSize(i32, ThemeSized),
|
||||
#[error("The ol' forker is not available")]
|
||||
NoForker,
|
||||
#[error("Repeat rate is negative")]
|
||||
|
|
@ -1066,6 +1116,10 @@ enum CphError {
|
|||
WorkspaceDoesNotExist(Workspace),
|
||||
#[error("Keyboard {0:?} does not exist")]
|
||||
KeyboardDoesNotExist(InputDevice),
|
||||
#[error("Colorable element {0} is not known")]
|
||||
UnknownColor(u32),
|
||||
#[error("Sized element {0} is not known")]
|
||||
UnknownSized(u32),
|
||||
#[error("Could not parse the message")]
|
||||
ParsingFailed(#[source] DecodeError),
|
||||
#[error("Could not process a `{0}` request")]
|
||||
|
|
|
|||
|
|
@ -422,7 +422,14 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toggle_floating(self: &Rc<Self>) {
|
||||
pub fn get_floating(self: &Rc<Self>) -> Option<bool> {
|
||||
match self.keyboard_node.get().node_toplevel() {
|
||||
Some(tl) => Some(tl.tl_data().is_floating.get()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_floating(self: &Rc<Self>, floating: bool) {
|
||||
let tl = match self.keyboard_node.get().node_toplevel() {
|
||||
Some(tl) => tl,
|
||||
_ => return,
|
||||
|
|
@ -431,12 +438,15 @@ impl WlSeatGlobal {
|
|||
if data.is_fullscreen.get() {
|
||||
return;
|
||||
}
|
||||
if data.is_floating.get() == floating {
|
||||
return;
|
||||
}
|
||||
let parent = match data.parent.get() {
|
||||
Some(p) => p,
|
||||
_ => return,
|
||||
};
|
||||
if let Some(cn) = parent.clone().node_into_containing_node() {
|
||||
if parent.node_is_float() {
|
||||
if let Some(cn) = parent.node_into_containing_node() {
|
||||
if !floating {
|
||||
cn.cnode_remove_child2(tl.tl_as_node(), true);
|
||||
self.state.map_tiled(tl);
|
||||
} else if let Some(ws) = data.workspace.get() {
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
|
|||
tassert_eq!(window.tl.width.get(), 800);
|
||||
tassert_eq!(
|
||||
window.tl.height.get(),
|
||||
600 - 2 * (run.state.theme.title_height.get() + 1)
|
||||
600 - 2 * (run.state.theme.sizes.title_height.get() + 1)
|
||||
);
|
||||
|
||||
tassert_eq!(
|
||||
window.tl.server.node_absolute_position(),
|
||||
Rect::new_sized(
|
||||
0,
|
||||
2 * (run.state.theme.title_height.get() + 1),
|
||||
2 * (run.state.theme.sizes.title_height.get() + 1),
|
||||
window.tl.width.get(),
|
||||
window.tl.height.get(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
|
|||
let window2 = client.create_window().await?;
|
||||
window2.map().await?;
|
||||
|
||||
let otop = 2 * (run.state.theme.title_height.get() + 1);
|
||||
let bw = run.state.theme.border_width.get();
|
||||
let otop = 2 * (run.state.theme.sizes.title_height.get() + 1);
|
||||
let bw = run.state.theme.sizes.border_width.get();
|
||||
|
||||
tassert_eq!(
|
||||
window.tl.server.node_absolute_position(),
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ impl Framebuffer {
|
|||
result: &mut RenderResult,
|
||||
) {
|
||||
let _ = self.ctx.ctx.with_current(|| {
|
||||
let c = state.theme.background_color.get();
|
||||
let c = state.theme.colors.background.get();
|
||||
unsafe {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
|
||||
glViewport(0, 0, self.gl.width, self.gl.height);
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ impl Renderer<'_> {
|
|||
render_layer!(output.layers[0]);
|
||||
render_layer!(output.layers[1]);
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
{
|
||||
let c = Color::BLACK;
|
||||
let c = theme.colors.bar_background.get();
|
||||
self.fill_boxes2(
|
||||
slice::from_ref(&Rect::new_sized(0, 0, opos.width(), th).unwrap()),
|
||||
&c,
|
||||
|
|
@ -106,12 +106,12 @@ impl Renderer<'_> {
|
|||
);
|
||||
let rd = output.render_data.borrow_mut();
|
||||
if let Some(aw) = &rd.active_workspace {
|
||||
let c = theme.active_title_color.get();
|
||||
let c = theme.colors.focused_title_background.get();
|
||||
self.fill_boxes2(slice::from_ref(aw), &c, x, y);
|
||||
}
|
||||
let c = theme.underline_color.get();
|
||||
let c = theme.colors.separator.get();
|
||||
self.fill_boxes2(slice::from_ref(&rd.underline), &c, x, y);
|
||||
let c = theme.title_color.get();
|
||||
let c = theme.colors.unfocused_title_background.get();
|
||||
self.fill_boxes2(&rd.inactive_workspaces, &c, x, y);
|
||||
for title in &rd.titles {
|
||||
self.render_texture(&title.tex, x + title.x, y + title.y, ARGB8888);
|
||||
|
|
@ -208,16 +208,21 @@ impl Renderer<'_> {
|
|||
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
||||
{
|
||||
let rd = container.render_data.borrow_mut();
|
||||
let c = self.state.theme.title_color.get();
|
||||
let c = self.state.theme.colors.unfocused_title_background.get();
|
||||
self.fill_boxes2(&rd.title_rects, &c, x, y);
|
||||
let c = self.state.theme.active_title_color.get();
|
||||
let c = self.state.theme.colors.focused_title_background.get();
|
||||
self.fill_boxes2(&rd.active_title_rects, &c, x, y);
|
||||
let c = self.state.theme.underline_color.get();
|
||||
let c = self.state.theme.colors.separator.get();
|
||||
self.fill_boxes2(&rd.underline_rects, &c, x, y);
|
||||
let c = self.state.theme.border_color.get();
|
||||
let c = self.state.theme.colors.border.get();
|
||||
self.fill_boxes2(&rd.border_rects, &c, x, y);
|
||||
if let Some(lar) = &rd.last_active_rect {
|
||||
let c = self.state.theme.last_active_color.get();
|
||||
let c = self
|
||||
.state
|
||||
.theme
|
||||
.colors
|
||||
.focused_inactive_title_background
|
||||
.get();
|
||||
self.fill_boxes2(std::slice::from_ref(lar), &c, x, y);
|
||||
}
|
||||
for title in &rd.titles {
|
||||
|
|
@ -379,14 +384,14 @@ impl Renderer<'_> {
|
|||
};
|
||||
let pos = floating.position.get();
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let bc = theme.border_color.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let bc = theme.colors.border.get();
|
||||
let tc = match floating.active.get() {
|
||||
true => theme.active_title_color.get(),
|
||||
false => theme.title_color.get(),
|
||||
true => theme.colors.focused_title_background.get(),
|
||||
false => theme.colors.unfocused_title_background.get(),
|
||||
};
|
||||
let uc = theme.underline_color.get();
|
||||
let uc = theme.colors.separator.get();
|
||||
let borders = [
|
||||
Rect::new_sized(x, y, pos.width(), bw).unwrap(),
|
||||
Rect::new_sized(x, y + bw, bw, pos.height() - bw).unwrap(),
|
||||
|
|
|
|||
|
|
@ -345,8 +345,8 @@ impl State {
|
|||
workspace: &Rc<WorkspaceNode>,
|
||||
) {
|
||||
node.clone().tl_set_workspace(workspace);
|
||||
width += 2 * self.theme.border_width.get();
|
||||
height += 2 * self.theme.border_width.get() + self.theme.title_height.get();
|
||||
width += 2 * self.theme.sizes.border_width.get();
|
||||
height += 2 * self.theme.sizes.border_width.get() + self.theme.sizes.title_height.get();
|
||||
let output = workspace.output.get();
|
||||
let output_rect = output.global.pos.get();
|
||||
let position = {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ pub fn render(
|
|||
render2(ctx, 1, width, height, 1, font, text, color, true, false)
|
||||
}
|
||||
|
||||
pub fn render2(
|
||||
fn render2(
|
||||
ctx: &Rc<RenderContext>,
|
||||
x: i32,
|
||||
width: i32,
|
||||
|
|
|
|||
175
src/theme.rs
175
src/theme.rs
|
|
@ -8,22 +8,6 @@ pub struct Color {
|
|||
pub a: f32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub const GREY: Self = Self {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
b: 0.8,
|
||||
a: 1.0,
|
||||
};
|
||||
|
||||
pub const BLACK: Self = Self {
|
||||
r: 0.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
fn to_f32(c: u8) -> f32 {
|
||||
c as f32 / 255f32
|
||||
}
|
||||
|
|
@ -33,6 +17,15 @@ fn to_u8(c: f32) -> u8 {
|
|||
}
|
||||
|
||||
impl Color {
|
||||
pub fn from_rgb(r: u8, g: u8, b: u8) -> Self {
|
||||
Self {
|
||||
r: to_f32(r),
|
||||
g: to_f32(g),
|
||||
b: to_f32(b),
|
||||
a: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rgba_straight(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
let alpha = to_f32(a);
|
||||
Self {
|
||||
|
|
@ -51,39 +44,145 @@ impl Color {
|
|||
|
||||
impl From<jay_config::theme::Color> for Color {
|
||||
fn from(f: jay_config::theme::Color) -> Self {
|
||||
Self {
|
||||
r: to_f32(f.r),
|
||||
g: to_f32(f.g),
|
||||
b: to_f32(f.b),
|
||||
a: to_f32(f.a),
|
||||
let [r, g, b, a] = f.to_f32_premultiplied();
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! colors {
|
||||
($($name:ident = ($r:expr, $g:expr, $b:expr),)*) => {
|
||||
pub struct ThemeColors {
|
||||
$(
|
||||
pub $name: Cell<Color>,
|
||||
)*
|
||||
}
|
||||
|
||||
impl ThemeColors {
|
||||
pub fn reset(&self) {
|
||||
let default = Self::default();
|
||||
$(
|
||||
self.$name.set(default.$name.get());
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ThemeColors {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
$(
|
||||
$name: Cell::new(Color::from_rgb($r, $g, $b)),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colors! {
|
||||
background = (0x00, 0x10, 0x19),
|
||||
unfocused_title_background = (0x22, 0x22, 0x22),
|
||||
focused_title_background = (0x28, 0x55, 0x77),
|
||||
focused_inactive_title_background = (0x5f, 0x67, 0x6a),
|
||||
unfocused_title_text = (0x88, 0x88, 0x88),
|
||||
focused_title_text = (0xff, 0xff, 0xff),
|
||||
focused_inactive_title_text = (0xff, 0xff, 0xff),
|
||||
separator = (0x33, 0x33, 0x33),
|
||||
border = (0x3f, 0x47, 0x4a),
|
||||
bar_background = (0x00, 0x00, 0x00),
|
||||
bar_text = (0xff, 0xff, 0xff),
|
||||
}
|
||||
|
||||
macro_rules! sizes {
|
||||
($($name:ident = ($min:expr, $max:expr, $def:expr),)*) => {
|
||||
pub struct ThemeSizes {
|
||||
$(
|
||||
pub $name: Cell<i32>,
|
||||
)*
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum ThemeSized {
|
||||
$(
|
||||
$name,
|
||||
)*
|
||||
}
|
||||
|
||||
impl ThemeSized {
|
||||
pub fn min(self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
Self::$name => $min,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max(self) -> i32 {
|
||||
match self {
|
||||
$(
|
||||
Self::$name => $max,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn field(self, theme: &Theme) -> &Cell<i32> {
|
||||
let sizes = &theme.sizes;
|
||||
match self {
|
||||
$(
|
||||
Self::$name => &sizes.$name,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
$(
|
||||
Self::$name => stringify!($name),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ThemeSizes {
|
||||
pub fn reset(&self) {
|
||||
let default = Self::default();
|
||||
$(
|
||||
self.$name.set(default.$name.get());
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ThemeSizes {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
$(
|
||||
$name: Cell::new($def),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sizes! {
|
||||
title_height = (1, 1000, 17),
|
||||
border_width = (1, 1000, 4),
|
||||
}
|
||||
|
||||
pub const DEFAULT_FONT: &str = "monospace 8";
|
||||
|
||||
pub struct Theme {
|
||||
pub background_color: Cell<Color>,
|
||||
pub title_color: Cell<Color>,
|
||||
pub active_title_color: Cell<Color>,
|
||||
pub underline_color: Cell<Color>,
|
||||
pub border_color: Cell<Color>,
|
||||
pub last_active_color: Cell<Color>,
|
||||
pub title_height: Cell<i32>,
|
||||
pub border_width: Cell<i32>,
|
||||
pub colors: ThemeColors,
|
||||
pub sizes: ThemeSizes,
|
||||
pub font: RefCell<String>,
|
||||
}
|
||||
|
||||
impl Default for Theme {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
background_color: Cell::new(Color::from_rgba_straight(0x00, 0x10, 0x19, 255)),
|
||||
last_active_color: Cell::new(Color::from_rgba_straight(0x5f, 0x67, 0x6a, 255)),
|
||||
title_color: Cell::new(Color::from_rgba_straight(0x22, 0x22, 0x22, 255)),
|
||||
active_title_color: Cell::new(Color::from_rgba_straight(0x28, 0x55, 0x77, 255)),
|
||||
underline_color: Cell::new(Color::from_rgba_straight(0x33, 0x33, 0x33, 255)),
|
||||
border_color: Cell::new(Color::from_rgba_straight(0x3f, 0x47, 0x4a, 255)),
|
||||
title_height: Cell::new(17),
|
||||
border_width: Cell::new(4),
|
||||
font: RefCell::new("monospace 8".to_string()),
|
||||
colors: Default::default(),
|
||||
sizes: Default::default(),
|
||||
font: RefCell::new(DEFAULT_FONT.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use {
|
|||
render::{Renderer, Texture},
|
||||
state::State,
|
||||
text,
|
||||
theme::Color,
|
||||
tree::{
|
||||
walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId,
|
||||
ToplevelData, ToplevelNode, WorkspaceNode,
|
||||
|
|
@ -26,7 +25,6 @@ use {
|
|||
},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
isnt::std_1::vec::IsntVecExt,
|
||||
jay_config::{Axis, Direction},
|
||||
smallvec::SmallVec,
|
||||
std::{
|
||||
|
|
@ -368,8 +366,8 @@ impl ContainerNode {
|
|||
self.mono_content
|
||||
.set(child.content.get().at_point(mb.x1(), mb.y1()));
|
||||
|
||||
let th = self.state.theme.title_height.get();
|
||||
let bw = self.state.theme.border_width.get();
|
||||
let th = self.state.theme.sizes.title_height.get();
|
||||
let bw = self.state.theme.sizes.border_width.get();
|
||||
let num_children = self.num_children.get() as i32;
|
||||
let content_width = self.width.get().sub(bw * (num_children - 1)).max(0);
|
||||
let width_per_child = content_width / num_children;
|
||||
|
|
@ -390,8 +388,8 @@ impl ContainerNode {
|
|||
|
||||
fn perform_split_layout(self: &Rc<Self>) {
|
||||
let sum_factors = self.sum_factors.get();
|
||||
let border_width = self.state.theme.border_width.get();
|
||||
let title_height = self.state.theme.title_height.get();
|
||||
let border_width = self.state.theme.sizes.border_width.get();
|
||||
let title_height = self.state.theme.sizes.title_height.get();
|
||||
let split = self.split.get();
|
||||
let (content_size, other_content_size) = match split {
|
||||
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
|
||||
|
|
@ -476,8 +474,8 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
fn update_content_size(&self) {
|
||||
let border_width = self.state.theme.border_width.get();
|
||||
let title_height = self.state.theme.title_height.get();
|
||||
let border_width = self.state.theme.sizes.border_width.get();
|
||||
let title_height = self.state.theme.sizes.title_height.get();
|
||||
let nc = self.num_children.get();
|
||||
match self.split.get() {
|
||||
ContainerSplit::Horizontal => {
|
||||
|
|
@ -508,7 +506,7 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
fn pointer_move(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, mut x: i32, mut y: i32) {
|
||||
let title_height = self.state.theme.title_height.get();
|
||||
let title_height = self.state.theme.sizes.title_height.get();
|
||||
let mut seats = self.seats.borrow_mut();
|
||||
let seat_state = seats.entry(seat.id()).or_insert_with(|| SeatState {
|
||||
cursor: KnownCursor::Default,
|
||||
|
|
@ -630,8 +628,8 @@ impl ContainerNode {
|
|||
let mut rd = self.render_data.borrow_mut();
|
||||
let rd = rd.deref_mut();
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let font = theme.font.borrow_mut();
|
||||
let cwidth = self.width.get();
|
||||
let cheight = self.height.get();
|
||||
|
|
@ -641,9 +639,11 @@ impl ContainerNode {
|
|||
rd.active_title_rects.clear();
|
||||
rd.border_rects.clear();
|
||||
rd.underline_rects.clear();
|
||||
rd.last_active_rect.take();
|
||||
let last_active = self.focus_history.last().map(|v| v.node.node_id());
|
||||
let mono = self.mono_child.get().is_some();
|
||||
let split = self.split.get();
|
||||
let have_active = self.children.iter().any(|c| c.active.get());
|
||||
for (i, child) in self.children.iter().enumerate() {
|
||||
let rect = child.title_rect.get();
|
||||
if i > 0 {
|
||||
|
|
@ -656,14 +656,16 @@ impl ContainerNode {
|
|||
};
|
||||
rd.border_rects.push(rect.unwrap());
|
||||
}
|
||||
if child.active.get() {
|
||||
let color = if child.active.get() {
|
||||
rd.active_title_rects.push(rect);
|
||||
theme.colors.focused_title_text.get()
|
||||
} else if !have_active && last_active == Some(child.node.node_id()) {
|
||||
rd.last_active_rect = Some(rect);
|
||||
theme.colors.focused_inactive_title_text.get()
|
||||
} else {
|
||||
rd.title_rects.push(rect);
|
||||
}
|
||||
if last_active == Some(child.node.node_id()) {
|
||||
rd.last_active_rect = Some(rect);
|
||||
}
|
||||
theme.colors.unfocused_title_text.get()
|
||||
};
|
||||
if !mono {
|
||||
let rect = Rect::new_sized(rect.x1(), rect.y2(), rect.width(), 1).unwrap();
|
||||
rd.underline_rects.push(rect);
|
||||
|
|
@ -674,7 +676,7 @@ impl ContainerNode {
|
|||
break 'render_title;
|
||||
}
|
||||
if let Some(ctx) = &ctx {
|
||||
match text::render(ctx, rect.width(), th, &font, title.deref(), Color::GREY) {
|
||||
match text::render(ctx, rect.width(), th, &font, title.deref(), color) {
|
||||
Ok(t) => rd.titles.push(ContainerTitle {
|
||||
x: rect.x1(),
|
||||
y: rect.y1(),
|
||||
|
|
@ -691,9 +693,6 @@ impl ContainerNode {
|
|||
rd.underline_rects
|
||||
.push(Rect::new_sized(0, th, cwidth, 1).unwrap());
|
||||
}
|
||||
if rd.active_title_rects.is_not_empty() {
|
||||
rd.last_active_rect.take();
|
||||
}
|
||||
}
|
||||
|
||||
fn activate_child(self: &Rc<Self>, child: &NodeRef<ContainerChild>) {
|
||||
|
|
@ -1151,7 +1150,7 @@ impl Node for ContainerNode {
|
|||
Some(s) => s,
|
||||
_ => return,
|
||||
};
|
||||
if seat_data.y > self.state.theme.title_height.get() {
|
||||
if seat_data.y > self.state.theme.sizes.title_height.get() {
|
||||
return;
|
||||
}
|
||||
let cur_mc = match self.mono_child.get() {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use {
|
|||
render::{Renderer, Texture},
|
||||
state::State,
|
||||
text,
|
||||
theme::Color,
|
||||
tree::{
|
||||
walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId,
|
||||
StackedNode, ToplevelNode, WorkspaceNode,
|
||||
|
|
@ -144,8 +143,8 @@ impl FloatNode {
|
|||
};
|
||||
let pos = self.position.get();
|
||||
let theme = &self.state.theme;
|
||||
let bw = theme.border_width.get();
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
let cpos = Rect::new_sized(
|
||||
pos.x1() + bw,
|
||||
pos.y1() + bw + th + 1,
|
||||
|
|
@ -167,8 +166,12 @@ impl FloatNode {
|
|||
fn render_title(&self) {
|
||||
self.render_titles_scheduled.set(false);
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
let tc = match self.active.get() {
|
||||
true => theme.colors.focused_title_text.get(),
|
||||
false => theme.colors.unfocused_title_text.get(),
|
||||
};
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let font = theme.font.borrow_mut();
|
||||
let title = self.title.borrow_mut();
|
||||
self.title_texture.set(None);
|
||||
|
|
@ -180,8 +183,7 @@ impl FloatNode {
|
|||
Some(c) => c,
|
||||
_ => return,
|
||||
};
|
||||
let texture = match text::render(&ctx, pos.width() - 2 * bw, th, &font, &title, Color::GREY)
|
||||
{
|
||||
let texture = match text::render(&ctx, pos.width() - 2 * bw, th, &font, &title, tc) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||
|
|
@ -193,8 +195,8 @@ impl FloatNode {
|
|||
|
||||
fn pointer_move(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, x: i32, y: i32) {
|
||||
let theme = &self.state.theme;
|
||||
let bw = theme.border_width.get();
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
let mut seats = self.seats.borrow_mut();
|
||||
let seat_state = seats.entry(seat.id()).or_insert_with(|| SeatState {
|
||||
cursor: KnownCursor::Default,
|
||||
|
|
@ -370,8 +372,8 @@ impl Node for FloatNode {
|
|||
|
||||
fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let th = theme.sizes.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let pos = self.position.get();
|
||||
if x < bw || x >= pos.width() - bw {
|
||||
return FindTreeResult::AcceptsInput;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use {
|
|||
render::{Renderer, Texture},
|
||||
state::State,
|
||||
text,
|
||||
theme::Color,
|
||||
tree::{walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode},
|
||||
utils::{
|
||||
clonecell::CloneCell, errorfmt::ErrorFmt, linkedlist::LinkedList, scroller::Scroller,
|
||||
|
|
@ -53,6 +52,13 @@ impl OutputNode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_spaces_changed(self: &Rc<Self>) {
|
||||
self.update_render_data();
|
||||
if let Some(c) = self.workspace.get() {
|
||||
c.change_extents(&self.workspace_rect());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_render_data(&self) {
|
||||
let mut rd = self.render_data.borrow_mut();
|
||||
rd.titles.clear();
|
||||
|
|
@ -61,7 +67,8 @@ impl OutputNode {
|
|||
rd.status = None;
|
||||
let mut pos = 0;
|
||||
let font = self.state.theme.font.borrow_mut();
|
||||
let th = self.state.theme.title_height.get();
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.sizes.title_height.get();
|
||||
let active_id = self.workspace.get().map(|w| w.id);
|
||||
let width = self.global.pos.get().width();
|
||||
rd.underline = Rect::new_sized(0, th, width, 1).unwrap();
|
||||
|
|
@ -72,14 +79,17 @@ impl OutputNode {
|
|||
if th == 0 || ws.name.is_empty() {
|
||||
break 'create_texture;
|
||||
}
|
||||
let title =
|
||||
match text::render_fitting(&ctx, th, &font, &ws.name, Color::GREY, false) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", ws.name, ErrorFmt(e));
|
||||
break 'create_texture;
|
||||
}
|
||||
};
|
||||
let tc = match active_id == Some(ws.id) {
|
||||
true => theme.colors.focused_title_text.get(),
|
||||
false => theme.colors.unfocused_title_text.get(),
|
||||
};
|
||||
let title = match text::render_fitting(&ctx, th, &font, &ws.name, tc, false) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", ws.name, ErrorFmt(e));
|
||||
break 'create_texture;
|
||||
}
|
||||
};
|
||||
let mut x = pos + 1;
|
||||
if title.width() + 2 > title_width {
|
||||
title_width = title.width() + 2;
|
||||
|
|
@ -110,7 +120,8 @@ impl OutputNode {
|
|||
if status.is_empty() {
|
||||
break 'set_status;
|
||||
}
|
||||
let title = match text::render_fitting(&ctx, th, &font, &status, Color::GREY, true) {
|
||||
let tc = self.state.theme.colors.bar_text.get();
|
||||
let title = match text::render_fitting(&ctx, th, &font, &status, tc, true) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Could not render status {}: {}", status, ErrorFmt(e));
|
||||
|
|
@ -205,7 +216,7 @@ impl OutputNode {
|
|||
|
||||
fn workspace_rect(&self) -> Rect {
|
||||
let rect = self.global.pos.get();
|
||||
let th = self.state.theme.title_height.get();
|
||||
let th = self.state.theme.sizes.title_height.get();
|
||||
Rect::new_sized(
|
||||
rect.x1(),
|
||||
rect.y1() + th + 1,
|
||||
|
|
@ -384,7 +395,7 @@ impl Node for OutputNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
let bar_height = self.state.theme.title_height.get() + 1;
|
||||
let bar_height = self.state.theme.sizes.title_height.get() + 1;
|
||||
if y >= bar_height {
|
||||
y -= bar_height;
|
||||
let len = tree.len();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use {
|
|||
render::{Renderer, Texture},
|
||||
state::State,
|
||||
text,
|
||||
theme::Color,
|
||||
tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData, ToplevelNode},
|
||||
utils::{clonecell::CloneCell, errorfmt::ErrorFmt},
|
||||
},
|
||||
|
|
@ -54,7 +53,7 @@ impl PlaceholderNode {
|
|||
rect.height(),
|
||||
&font,
|
||||
"Fullscreen",
|
||||
Color::GREY,
|
||||
self.toplevel.state.theme.colors.unfocused_title_text.get(),
|
||||
false,
|
||||
) {
|
||||
Ok(t) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue