xcrab/xafter.txt
2023-04-17 10:39:58 -05:00

2641 lines
110 KiB
Plaintext

#![feature(prelude_import)]
#![warn(clippy::pedantic)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use std::fmt::{Debug, Display};
use breadx::{
auto::xproto::{GrabKeyRequest, GrabMode, KeyButMask, ModMask},
keyboard::KeyboardState, prelude::{AsyncDisplay, AsyncDisplayXprotoExt, MapState},
traits::DisplayBase, AsyncDisplayConnection, AsyncDisplayExt, BreadError,
ConfigureWindowParameters, Event, EventMask, Window,
};
use lazy_static::lazy_static;
use tokio::sync::mpsc::unbounded_channel;
mod config {
#![allow(dead_code, clippy::module_name_repetitions)]
use crate::msg_listener::Action;
use crate::Result;
use breadx::auto::xproto::KeyButMask;
use serde::{
de::{Deserializer, Visitor},
Deserialize,
};
use std::collections::HashMap;
use std::path::PathBuf;
pub struct XcrabConfig {
border_color: Option<u32>,
focused_color: Option<u32>,
border_size: Option<u16>,
gap_size: Option<u16>,
outer_gap_size: Option<u16>,
pub msg: Option<XcrabMsgConfig>,
#[allow(clippy::zero_sized_map_values)]
#[serde(default)]
pub binds: HashMap<Keybind, Action>,
}
#[automatically_derived]
impl ::core::clone::Clone for XcrabConfig {
#[inline]
fn clone(&self) -> XcrabConfig {
XcrabConfig {
border_color: ::core::clone::Clone::clone(&self.border_color),
focused_color: ::core::clone::Clone::clone(&self.focused_color),
border_size: ::core::clone::Clone::clone(&self.border_size),
gap_size: ::core::clone::Clone::clone(&self.gap_size),
outer_gap_size: ::core::clone::Clone::clone(&self.outer_gap_size),
msg: ::core::clone::Clone::clone(&self.msg),
binds: ::core::clone::Clone::clone(&self.binds),
}
}
}
#[automatically_derived]
impl ::core::fmt::Debug for XcrabConfig {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ = &[
"border_color",
"focused_color",
"border_size",
"gap_size",
"outer_gap_size",
"msg",
"binds",
];
let values: &[&dyn ::core::fmt::Debug] = &[
&self.border_color,
&self.focused_color,
&self.border_size,
&self.gap_size,
&self.outer_gap_size,
&self.msg,
&&self.binds,
];
::core::fmt::Formatter::debug_struct_fields_finish(
f,
"XcrabConfig",
names,
values,
)
}
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for XcrabConfig {
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
__field4,
__field5,
__field6,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3),
4u64 => _serde::__private::Ok(__Field::__field4),
5u64 => _serde::__private::Ok(__Field::__field5),
6u64 => _serde::__private::Ok(__Field::__field6),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"border_color" => _serde::__private::Ok(__Field::__field0),
"focused_color" => _serde::__private::Ok(__Field::__field1),
"border_size" => _serde::__private::Ok(__Field::__field2),
"gap_size" => _serde::__private::Ok(__Field::__field3),
"outer_gap_size" => _serde::__private::Ok(__Field::__field4),
"msg" => _serde::__private::Ok(__Field::__field5),
"binds" => _serde::__private::Ok(__Field::__field6),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"border_color" => _serde::__private::Ok(__Field::__field0),
b"focused_color" => _serde::__private::Ok(__Field::__field1),
b"border_size" => _serde::__private::Ok(__Field::__field2),
b"gap_size" => _serde::__private::Ok(__Field::__field3),
b"outer_gap_size" => _serde::__private::Ok(__Field::__field4),
b"msg" => _serde::__private::Ok(__Field::__field5),
b"binds" => _serde::__private::Ok(__Field::__field6),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de> {
marker: _serde::__private::PhantomData<XcrabConfig>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = XcrabConfig;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct XcrabConfig",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
Option<u32>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct XcrabConfig with 7 elements",
),
);
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
Option<u32>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"struct XcrabConfig with 7 elements",
),
);
}
};
let __field2 = match match _serde::de::SeqAccess::next_element::<
Option<u16>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
2usize,
&"struct XcrabConfig with 7 elements",
),
);
}
};
let __field3 = match match _serde::de::SeqAccess::next_element::<
Option<u16>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
3usize,
&"struct XcrabConfig with 7 elements",
),
);
}
};
let __field4 = match match _serde::de::SeqAccess::next_element::<
Option<u16>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
4usize,
&"struct XcrabConfig with 7 elements",
),
);
}
};
let __field5 = match match _serde::de::SeqAccess::next_element::<
Option<XcrabMsgConfig>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
5usize,
&"struct XcrabConfig with 7 elements",
),
);
}
};
let __field6 = match match _serde::de::SeqAccess::next_element::<
HashMap<Keybind, Action>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
_serde::__private::Default::default()
}
};
_serde::__private::Ok(XcrabConfig {
border_color: __field0,
focused_color: __field1,
border_size: __field2,
gap_size: __field3,
outer_gap_size: __field4,
msg: __field5,
binds: __field6,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<Option<u32>> = _serde::__private::None;
let mut __field1: _serde::__private::Option<Option<u32>> = _serde::__private::None;
let mut __field2: _serde::__private::Option<Option<u16>> = _serde::__private::None;
let mut __field3: _serde::__private::Option<Option<u16>> = _serde::__private::None;
let mut __field4: _serde::__private::Option<Option<u16>> = _serde::__private::None;
let mut __field5: _serde::__private::Option<
Option<XcrabMsgConfig>,
> = _serde::__private::None;
let mut __field6: _serde::__private::Option<
HashMap<Keybind, Action>,
> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<
__Field,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"border_color",
),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
Option<u32>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field1 => {
if _serde::__private::Option::is_some(&__field1) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"focused_color",
),
);
}
__field1 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
Option<u32>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field2 => {
if _serde::__private::Option::is_some(&__field2) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"border_size",
),
);
}
__field2 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
Option<u16>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field3 => {
if _serde::__private::Option::is_some(&__field3) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"gap_size",
),
);
}
__field3 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
Option<u16>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field4 => {
if _serde::__private::Option::is_some(&__field4) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"outer_gap_size",
),
);
}
__field4 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
Option<u16>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field5 => {
if _serde::__private::Option::is_some(&__field5) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("msg"),
);
}
__field5 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
Option<XcrabMsgConfig>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field6 => {
if _serde::__private::Option::is_some(&__field6) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("binds"),
);
}
__field6 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
HashMap<Keybind, Action>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("border_color") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field1 = match __field1 {
_serde::__private::Some(__field1) => __field1,
_serde::__private::None => {
match _serde::__private::de::missing_field(
"focused_color",
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field2 = match __field2 {
_serde::__private::Some(__field2) => __field2,
_serde::__private::None => {
match _serde::__private::de::missing_field("border_size") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field3 = match __field3 {
_serde::__private::Some(__field3) => __field3,
_serde::__private::None => {
match _serde::__private::de::missing_field("gap_size") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field4 = match __field4 {
_serde::__private::Some(__field4) => __field4,
_serde::__private::None => {
match _serde::__private::de::missing_field(
"outer_gap_size",
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field5 = match __field5 {
_serde::__private::Some(__field5) => __field5,
_serde::__private::None => {
match _serde::__private::de::missing_field("msg") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field6 = match __field6 {
_serde::__private::Some(__field6) => __field6,
_serde::__private::None => {
_serde::__private::Default::default()
}
};
_serde::__private::Ok(XcrabConfig {
border_color: __field0,
focused_color: __field1,
border_size: __field2,
gap_size: __field3,
outer_gap_size: __field4,
msg: __field5,
binds: __field6,
})
}
}
const FIELDS: &'static [&'static str] = &[
"border_color",
"focused_color",
"border_size",
"gap_size",
"outer_gap_size",
"msg",
"binds",
];
_serde::Deserializer::deserialize_struct(
__deserializer,
"XcrabConfig",
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<XcrabConfig>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
pub struct XcrabMsgConfig {
pub socket_path: PathBuf,
}
#[automatically_derived]
impl ::core::clone::Clone for XcrabMsgConfig {
#[inline]
fn clone(&self) -> XcrabMsgConfig {
XcrabMsgConfig {
socket_path: ::core::clone::Clone::clone(&self.socket_path),
}
}
}
#[automatically_derived]
impl ::core::fmt::Debug for XcrabMsgConfig {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(
f,
"XcrabMsgConfig",
"socket_path",
&&self.socket_path,
)
}
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for XcrabMsgConfig {
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"socket_path" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"socket_path" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de> {
marker: _serde::__private::PhantomData<XcrabMsgConfig>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = XcrabMsgConfig;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct XcrabMsgConfig",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
PathBuf,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct XcrabMsgConfig with 1 element",
),
);
}
};
_serde::__private::Ok(XcrabMsgConfig {
socket_path: __field0,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<PathBuf> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<
__Field,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"socket_path",
),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
PathBuf,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("socket_path") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(XcrabMsgConfig {
socket_path: __field0,
})
}
}
const FIELDS: &'static [&'static str] = &["socket_path"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"XcrabMsgConfig",
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<XcrabMsgConfig>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
const DEFAULT_BORDER_COLOR: u32 = 0xff_00_00;
const DEFAULT_FOCUSED_COLOR: u32 = 0x00_00_ff;
const DEFAULT_BORDER_SIZE: u16 = 5;
const DEFAULT_GAP_SIZE: u16 = 20;
impl Default for XcrabConfig {
fn default() -> Self {
Self {
border_color: Some(DEFAULT_BORDER_COLOR),
focused_color: Some(DEFAULT_FOCUSED_COLOR),
border_size: Some(DEFAULT_BORDER_SIZE),
gap_size: Some(DEFAULT_GAP_SIZE),
outer_gap_size: None,
msg: Some(XcrabMsgConfig::default()),
binds: HashMap::new(),
}
}
}
impl Default for XcrabMsgConfig {
fn default() -> Self {
let home_dir = get_home().expect("Error: $HOME variable not set");
Self {
socket_path: {
let res = ::alloc::fmt::format(
format_args!("{0}/.config/xcrab/msg.sock", home_dir),
);
res
}
.into(),
}
}
}
impl XcrabConfig {
pub fn border_color(&self) -> u32 {
self.border_color.unwrap_or(DEFAULT_BORDER_COLOR)
}
pub fn focused_color(&self) -> u32 {
self.focused_color.unwrap_or(DEFAULT_FOCUSED_COLOR)
}
pub fn border_size(&self) -> u16 {
self.border_size.unwrap_or(DEFAULT_BORDER_SIZE)
}
pub fn gap_size(&self) -> u16 {
self.gap_size.unwrap_or(DEFAULT_GAP_SIZE)
}
pub fn outer_gap_size(&self) -> u16 {
self.outer_gap_size.unwrap_or_else(|| self.gap_size())
}
}
pub fn load_file() -> Result<XcrabConfig> {
let home_dir = get_home()?;
let contents = std::fs::read_to_string({
let res = ::alloc::fmt::format(
format_args!("{0}/.config/xcrab/config.toml", home_dir),
);
res
})?;
let config: XcrabConfig = toml::from_str(&contents)?;
Ok(config)
}
fn get_home() -> Result<String> {
Ok(std::env::var("HOME")?)
}
struct ActionVisitor;
impl<'de> Visitor<'de> for ActionVisitor {
type Value = Action;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a valid WM action")
}
fn visit_str<E: serde::de::Error>(
self,
value: &str,
) -> std::result::Result<Self::Value, E> {
value.parse().map_err(|s| E::custom(s))
}
}
impl<'de> Deserialize<'de> for Action {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> std::result::Result<Self, D::Error> {
deserializer.deserialize_str(ActionVisitor)
}
}
pub struct Keybind {
pub key: char,
pub mods: KeyButMask,
}
#[automatically_derived]
impl ::core::clone::Clone for Keybind {
#[inline]
fn clone(&self) -> Keybind {
let _: ::core::clone::AssertParamIsClone<char>;
let _: ::core::clone::AssertParamIsClone<KeyButMask>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for Keybind {}
#[automatically_derived]
impl ::core::fmt::Debug for Keybind {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(
f,
"Keybind",
"key",
&self.key,
"mods",
&&self.mods,
)
}
}
#[automatically_derived]
impl ::core::hash::Hash for Keybind {
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.key, state);
::core::hash::Hash::hash(&self.mods, state)
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Keybind {}
#[automatically_derived]
impl ::core::cmp::PartialEq for Keybind {
#[inline]
fn eq(&self, other: &Keybind) -> bool {
self.key == other.key && self.mods == other.mods
}
}
#[automatically_derived]
impl ::core::marker::StructuralEq for Keybind {}
#[automatically_derived]
impl ::core::cmp::Eq for Keybind {
#[inline]
#[doc(hidden)]
#[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<char>;
let _: ::core::cmp::AssertParamIsEq<KeyButMask>;
}
}
struct KeybindVisitor;
impl<'de> Visitor<'de> for KeybindVisitor {
type Value = Keybind;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a keybind in the form of 'M-x'")
}
fn visit_str<E: serde::de::Error>(
self,
value: &str,
) -> std::result::Result<Self::Value, E> {
let mut mask = KeyButMask::default();
for part in value.split('-') {
if part.len() > 1 {
return Err(E::custom("parts may only contain one character"));
}
let c = part
.chars()
.next()
.ok_or_else(|| E::custom(
"parts must contain at least one character",
))?;
if c.is_ascii_uppercase() {
match c {
'C' => mask.set_control(true),
'S' => mask.set_shift(true),
'A' => mask.set_mod1(true),
'W' => mask.set_mod4(true),
_ => {
return Err(
E::custom({
let res = ::alloc::fmt::format(
format_args!("no such modifier: {0}", c),
);
res
}),
);
}
};
}
}
let c = value
.split('-')
.flat_map(str::chars)
.find(char::is_ascii_lowercase)
.ok_or_else(|| E::custom("must specify one normal key"))?
.to_ascii_uppercase();
Ok(Keybind { key: c, mods: mask })
}
}
impl<'de> Deserialize<'de> for Keybind {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> std::result::Result<Self, D::Error> {
deserializer.deserialize_str(KeybindVisitor)
}
}
}
mod msg_listener {
use crate::x11::client::XcrabWindowManager;
use crate::Result;
use breadx::AsyncDisplay;
use std::path::Path;
use std::str::FromStr;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::UnixListener;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use crate::XcrabError;
pub async fn listener_task<P: AsRef<Path>>(
socket_path: P,
sender: UnboundedSender<String>,
mut result_recv: UnboundedReceiver<Result<()>>,
) -> Result<()> {
let socket_path = socket_path.as_ref();
if socket_path.exists() {
std::fs::remove_file(socket_path)?;
}
let listener = UnixListener::bind(socket_path)?;
loop {
let (mut stream, _) = match listener.accept().await {
Ok(v) => v,
Err(_) => continue,
};
let mut buf = String::new();
stream.read_to_string(&mut buf).await?;
drop(sender.send(buf));
if let Err(e) = result_recv.recv().await.unwrap() {
stream
.write_all(
{
let res = ::alloc::fmt::format(format_args!("{0}", e));
res
}
.as_bytes(),
)
.await?;
} else {
stream.write_all(&[]).await?;
}
}
}
pub async fn on_recv<Dpy: AsyncDisplay + ?Sized>(
data: String,
manager: &mut XcrabWindowManager,
conn: &mut Dpy,
result_sender: &UnboundedSender<Result<()>>,
) -> Result<()> {
let res = { data.parse::<Action>() };
if let Ok(ref a) = res {
a.eval(manager, conn).await?;
}
drop(result_sender.send(res.map(|_| ())));
Ok(())
}
#[non_exhaustive]
pub enum Action {
Close,
}
#[automatically_derived]
impl ::core::fmt::Debug for Action {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Close")
}
}
#[automatically_derived]
impl ::core::clone::Clone for Action {
#[inline]
fn clone(&self) -> Action {
Action::Close
}
}
impl FromStr for Action {
type Err = XcrabError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
#[allow(clippy::enum_glob_use)]
use Action::*;
let parts: Vec<String> = s
.split(' ')
.map(str::to_ascii_lowercase)
.filter(|s| !s.is_empty())
.collect();
if parts.is_empty() {
return Err(XcrabError::Custom(String::from("No action provided")));
}
if parts[0].eq_ignore_ascii_case("close") {
Ok(Close)
} else {
Err(
XcrabError::Custom({
let res = ::alloc::fmt::format(
format_args!("Unknown action: {0}", s),
);
res
}),
)
}
}
}
impl Action {
pub async fn eval<Dpy: AsyncDisplay + ?Sized>(
&self,
manager: &mut XcrabWindowManager,
conn: &mut Dpy,
) -> Result<()> {
#[allow(clippy::enum_glob_use)]
use Action::*;
match self {
Close => manager.destroy_focused_client(conn).await?,
}
Ok(())
}
}
}
mod x11 {
pub mod client {
use breadx::auto::xproto::{KeyButMask, Keycode, Keysym};
use breadx::{
auto::xproto::{ClientMessageEvent, InputFocus, SetInputFocusRequest},
client_message_data::ClientMessageData,
prelude::{AsByteSequence, AsyncDisplayXprotoExt, PropertyType, SetMode},
AsyncDisplay, AsyncDisplayExt, Atom, BreadError, ConfigureWindowParameters,
ErrorCode, Event, EventMask, KeyboardState, Window, WindowParameters, XidType,
};
use slotmap::{new_key_type, SlotMap};
use std::{collections::HashMap, future::Future, pin::Pin, slice};
use crate::{Result, XcrabError, CONFIG};
pub enum Direction {
Up,
Down,
Left,
Right,
}
#[automatically_derived]
impl ::core::fmt::Debug for Direction {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(
f,
match self {
Direction::Up => "Up",
Direction::Down => "Down",
Direction::Left => "Left",
Direction::Right => "Right",
},
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for Direction {
#[inline]
fn clone(&self) -> Direction {
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for Direction {}
pub enum Directionality {
Horizontal,
Vertical,
}
#[automatically_derived]
impl ::core::fmt::Debug for Directionality {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(
f,
match self {
Directionality::Horizontal => "Horizontal",
Directionality::Vertical => "Vertical",
},
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for Directionality {
#[inline]
fn clone(&self) -> Directionality {
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for Directionality {}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Directionality {}
#[automatically_derived]
impl ::core::cmp::PartialEq for Directionality {
#[inline]
fn eq(&self, other: &Directionality) -> bool {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
__self_tag == __arg1_tag
}
}
#[automatically_derived]
impl ::core::marker::StructuralEq for Directionality {}
#[automatically_derived]
impl ::core::cmp::Eq for Directionality {
#[inline]
#[doc(hidden)]
#[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () {}
}
pub struct Dimensions {
x: u16,
y: u16,
width: u16,
height: u16,
}
#[automatically_derived]
impl ::core::fmt::Debug for Dimensions {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(
f,
"Dimensions",
"x",
&self.x,
"y",
&self.y,
"width",
&self.width,
"height",
&&self.height,
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for Dimensions {
#[inline]
fn clone(&self) -> Dimensions {
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for Dimensions {}
#[automatically_derived]
impl ::core::default::Default for Dimensions {
#[inline]
fn default() -> Dimensions {
Dimensions {
x: ::core::default::Default::default(),
y: ::core::default::Default::default(),
width: ::core::default::Default::default(),
height: ::core::default::Default::default(),
}
}
}
impl Dimensions {
fn split(self, direction: Directionality, count: usize) -> Vec<Self> {
let count_u16 = u16::try_from(count).unwrap();
match direction {
Directionality::Horizontal => {
let amount_for_windows = self.width
- CONFIG.gap_size() * (count_u16 - 1);
let excess = amount_for_windows % count_u16;
let window_size = amount_for_windows / count_u16;
let window_stride = window_size + CONFIG.gap_size();
(0..count.try_into().unwrap())
.map(|i| Dimensions {
x: self.x + i * window_stride
+ if i < excess { 1 } else { 0 },
width: window_size,
..self
})
.collect()
}
Directionality::Vertical => {
let amount_for_windows = self.height
- CONFIG.gap_size() * (count_u16 - 1);
let excess = amount_for_windows % count_u16;
let window_size = amount_for_windows / count_u16;
let window_stride = window_size + CONFIG.gap_size();
(0..count.try_into().unwrap())
.map(|i| Dimensions {
y: self.y + i * window_stride
+ if i < excess { 1 } else { 0 },
height: window_size,
..self
})
.collect()
}
}
}
}
#[repr(transparent)]
struct XcrabKey(::slotmap::KeyData);
#[automatically_derived]
impl ::core::marker::Copy for XcrabKey {}
#[automatically_derived]
impl ::core::clone::Clone for XcrabKey {
#[inline]
fn clone(&self) -> XcrabKey {
let _: ::core::clone::AssertParamIsClone<::slotmap::KeyData>;
*self
}
}
#[automatically_derived]
impl ::core::default::Default for XcrabKey {
#[inline]
fn default() -> XcrabKey {
XcrabKey(::core::default::Default::default())
}
}
#[automatically_derived]
impl ::core::marker::StructuralEq for XcrabKey {}
#[automatically_derived]
impl ::core::cmp::Eq for XcrabKey {
#[inline]
#[doc(hidden)]
#[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<::slotmap::KeyData>;
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for XcrabKey {}
#[automatically_derived]
impl ::core::cmp::PartialEq for XcrabKey {
#[inline]
fn eq(&self, other: &XcrabKey) -> bool {
self.0 == other.0
}
}
#[automatically_derived]
impl ::core::cmp::Ord for XcrabKey {
#[inline]
fn cmp(&self, other: &XcrabKey) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for XcrabKey {
#[inline]
fn partial_cmp(
&self,
other: &XcrabKey,
) -> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::hash::Hash for XcrabKey {
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}
#[automatically_derived]
impl ::core::fmt::Debug for XcrabKey {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(
f,
"XcrabKey",
&&self.0,
)
}
}
impl From<::slotmap::KeyData> for XcrabKey {
fn from(k: ::slotmap::KeyData) -> Self {
XcrabKey(k)
}
}
unsafe impl ::slotmap::Key for XcrabKey {
fn data(&self) -> ::slotmap::KeyData {
self.0
}
}
pub struct XcrabWindowManager {
clients: HashMap<Window, XcrabKey>,
rects: SlotMap<XcrabKey, Rectangle>,
focused: Option<Window>,
}
#[automatically_derived]
impl ::core::fmt::Debug for XcrabWindowManager {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(
f,
"XcrabWindowManager",
"clients",
&self.clients,
"rects",
&self.rects,
"focused",
&&self.focused,
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for XcrabWindowManager {
#[inline]
fn clone(&self) -> XcrabWindowManager {
XcrabWindowManager {
clients: ::core::clone::Clone::clone(&self.clients),
rects: ::core::clone::Clone::clone(&self.rects),
focused: ::core::clone::Clone::clone(&self.focused),
}
}
}
#[automatically_derived]
impl ::core::default::Default for XcrabWindowManager {
#[inline]
fn default() -> XcrabWindowManager {
XcrabWindowManager {
clients: ::core::default::Default::default(),
rects: ::core::default::Default::default(),
focused: ::core::default::Default::default(),
}
}
}
struct Rectangle {
parent: XcrabKey,
cached_dimensions: Dimensions,
contents: RectangleContents,
}
#[automatically_derived]
impl ::core::fmt::Debug for Rectangle {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(
f,
"Rectangle",
"parent",
&self.parent,
"cached_dimensions",
&self.cached_dimensions,
"contents",
&&self.contents,
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for Rectangle {
#[inline]
fn clone(&self) -> Rectangle {
Rectangle {
parent: ::core::clone::Clone::clone(&self.parent),
cached_dimensions: ::core::clone::Clone::clone(
&self.cached_dimensions,
),
contents: ::core::clone::Clone::clone(&self.contents),
}
}
}
impl Rectangle {
fn unwrap_pane(&self) -> &Pane {
match &self.contents {
RectangleContents::Pane(pane) => pane,
RectangleContents::Client(_) => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
}
}
fn unwrap_client(&self) -> &Client {
match &self.contents {
RectangleContents::Pane(_) => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
RectangleContents::Client(client) => client,
}
}
fn unwrap_pane_mut(&mut self) -> &mut Pane {
match &mut self.contents {
RectangleContents::Pane(pane) => pane,
RectangleContents::Client(_) => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
}
}
fn unwrap_client_mut(&mut self) -> &mut Client {
match &mut self.contents {
RectangleContents::Pane(_) => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
RectangleContents::Client(client) => client,
}
}
}
enum RectangleContents {
Pane(Pane),
Client(Client),
}
#[automatically_derived]
impl ::core::fmt::Debug for RectangleContents {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
RectangleContents::Pane(__self_0) => {
::core::fmt::Formatter::debug_tuple_field1_finish(
f,
"Pane",
&__self_0,
)
}
RectangleContents::Client(__self_0) => {
::core::fmt::Formatter::debug_tuple_field1_finish(
f,
"Client",
&__self_0,
)
}
}
}
}
#[automatically_derived]
impl ::core::clone::Clone for RectangleContents {
#[inline]
fn clone(&self) -> RectangleContents {
match self {
RectangleContents::Pane(__self_0) => {
RectangleContents::Pane(::core::clone::Clone::clone(__self_0))
}
RectangleContents::Client(__self_0) => {
RectangleContents::Client(::core::clone::Clone::clone(__self_0))
}
}
}
}
struct Pane {
children: Vec<XcrabKey>,
directionality: Directionality,
}
#[automatically_derived]
impl ::core::fmt::Debug for Pane {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(
f,
"Pane",
"children",
&self.children,
"directionality",
&&self.directionality,
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for Pane {
#[inline]
fn clone(&self) -> Pane {
Pane {
children: ::core::clone::Clone::clone(&self.children),
directionality: ::core::clone::Clone::clone(&self.directionality),
}
}
}
struct Client {
frame: FramedWindow,
}
#[automatically_derived]
impl ::core::fmt::Debug for Client {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(
f,
"Client",
"frame",
&&self.frame,
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for Client {
#[inline]
fn clone(&self) -> Client {
let _: ::core::clone::AssertParamIsClone<FramedWindow>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for Client {}
impl XcrabWindowManager {
pub fn new() -> Self {
XcrabWindowManager::default()
}
/// Given the `rect_key` from a `parent -> rect` relationship, makes A
/// `parent -> new_pane -> rect` relationship, then returns `new_pane_key`
fn insert_pane_above(
&mut self,
rect_key: XcrabKey,
directionality: Directionality,
) -> Option<XcrabKey> {
let rect = self.rects.get(rect_key)?;
let rect_dimensions = rect.cached_dimensions;
let parent_key = rect.parent;
let new_pane = Rectangle {
parent: parent_key,
cached_dimensions: rect_dimensions,
contents: RectangleContents::Pane(Pane {
children: <[_]>::into_vec(
#[rustc_box]
::alloc::boxed::Box::new([rect_key]),
),
directionality,
}),
};
let new_pane_key = if parent_key == rect_key {
self.rects
.insert_with_key(|key| Rectangle {
parent: key,
..new_pane
})
} else {
let new_pane_key = self.rects.insert(new_pane);
let parent_pane = self
.rects
.get_mut(parent_key)
.unwrap()
.unwrap_pane_mut();
let index = parent_pane
.children
.iter()
.copied()
.position(|v| v == rect_key)
.unwrap();
parent_pane.children[index] = new_pane_key;
new_pane_key
};
let rect = self.rects.get_mut(rect_key).unwrap();
rect.parent = new_pane_key;
Some(new_pane_key)
}
async fn focus_update_map<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
frame: FramedWindow,
parent_key: XcrabKey,
) -> Result<()> {
let win = frame.win;
self.focused = Some(win);
self.update_rectangle(conn, parent_key, None).await?;
frame.map(conn).await?;
self.update_focused(conn).await?;
Ok(())
}
/// Tells x about the currently focused window.
pub async fn update_focused<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
) -> Result<()> {
let mut req = SetInputFocusRequest {
req_type: 42,
revert_to: InputFocus::None,
length: 3,
focus: Window::from_xid(0),
time: 0,
};
if let Some(focus) = self.focused {
req.focus = focus;
}
conn.exchange_request_async(req).await?;
Ok(())
}
/// Adds a new client.
pub async fn add_client<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
win: Window,
) -> Result<()> {
self.add_client_direction(conn, win, Direction::Right).await
}
/// Adds a new client in the given direction from the focused window.
pub async fn add_client_direction<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
win: Window,
direction: Direction,
) -> Result<()> {
#[allow(clippy::enum_glob_use)]
use {Direction::*, Directionality::*};
let focused = match self.focused {
Some(v) => v,
None => return self.add_first_client(conn, win).await,
};
let frame = frame(conn, win).await?;
let focused_client_key = *self
.clients
.get(&focused)
.ok_or(XcrabError::ClientDoesntExist)?;
let target_directionality = match direction {
Up | Down => Vertical,
Left | Right => Horizontal,
};
let mut child_key = focused_client_key;
let parent_key = loop {
let parent_key = self.rects.get(child_key).unwrap().parent;
if parent_key == child_key {
break self
.insert_pane_above(child_key, target_directionality)
.unwrap();
}
let parent = self.rects.get(parent_key).unwrap();
if parent.unwrap_pane().directionality == target_directionality {
break parent_key;
}
child_key = parent_key;
};
let new_rect_key = self
.rects
.insert(Rectangle {
parent: parent_key,
cached_dimensions: Dimensions::default(),
contents: RectangleContents::Client(Client { frame }),
});
let parent_pane = self
.rects
.get_mut(parent_key)
.unwrap()
.unwrap_pane_mut();
let mut index = parent_pane
.children
.iter()
.copied()
.position(|v| v == child_key)
.unwrap();
if let Down | Right = direction {
index += 1;
}
parent_pane.children.insert(index, new_rect_key);
self.clients.insert(win, new_rect_key);
self.focus_update_map(conn, frame, parent_key).await?;
Ok(())
}
/// Adds a new client in the given direction directly adjacent to the focused window, creating a new pane if needed.
pub async fn add_client_direction_immediate<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
win: Window,
direction: Direction,
) -> Result<()> {
#[allow(clippy::enum_glob_use)]
use {Direction::*, Directionality::*};
let focused = match self.focused {
Some(v) => v,
None => return self.add_first_client(conn, win).await,
};
let frame = frame(conn, win).await?;
let focused_client_key = *self.clients.get(&focused).unwrap();
let focused_client = self.rects.get(focused_client_key).unwrap();
let mut parent_key = focused_client.parent;
let parent_pane_dir = match &self.rects.get(parent_key).unwrap().contents
{
RectangleContents::Pane(pane) => Some(pane.directionality),
RectangleContents::Client(_) => None,
};
let target_directionality = match direction {
Up | Down => Vertical,
Left | Right => Horizontal,
};
if parent_pane_dir.is_none()
|| parent_pane_dir.unwrap() != target_directionality
{
parent_key = self
.insert_pane_above(focused_client_key, target_directionality)
.unwrap();
}
let new_rect_key = self
.rects
.insert(Rectangle {
parent: parent_key,
cached_dimensions: Dimensions::default(),
contents: RectangleContents::Client(Client { frame }),
});
let parent_pane = self
.rects
.get_mut(parent_key)
.unwrap()
.unwrap_pane_mut();
let mut index = parent_pane
.children
.iter()
.copied()
.position(|v| v == focused_client_key)
.unwrap();
if let Down | Right = direction {
index += 1;
}
parent_pane.children.insert(index, new_rect_key);
self.clients.insert(win, new_rect_key);
self.focus_update_map(conn, frame, parent_key).await?;
Ok(())
}
async fn add_first_client<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
win: Window,
) -> Result<()> {
let frame = frame(conn, win).await?;
let root_geo = conn.default_root().geometry_immediate_async(conn).await?;
let outer_gap_size = CONFIG.outer_gap_size();
let key = self
.rects
.insert_with_key(|key| Rectangle {
parent: key,
cached_dimensions: Dimensions {
x: u16::try_from(root_geo.x).unwrap() + outer_gap_size,
y: u16::try_from(root_geo.y).unwrap() + outer_gap_size,
width: root_geo.width - 2 * outer_gap_size,
height: root_geo.height - 2 * outer_gap_size,
},
contents: RectangleContents::Client(Client { frame }),
});
self.clients.insert(win, key);
self.focus_update_map(conn, frame, key).await?;
Ok(())
}
#[must_use]
fn update_rectangle<'a, Dpy: AsyncDisplay + ?Sized>(
&'a mut self,
conn: &'a mut Dpy,
key: XcrabKey,
dimensions: Option<Dimensions>,
) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> {
Box::pin(async move {
let rect = self
.rects
.get_mut(key)
.ok_or(XcrabError::ClientDoesntExist)?;
let dimensions = dimensions.unwrap_or(rect.cached_dimensions);
rect.cached_dimensions = dimensions;
match &mut rect.contents {
RectangleContents::Pane(pane) => {
if !pane.children.is_empty() {
let new_dimensions = dimensions
.split(pane.directionality, pane.children.len());
for (key, dimensions) in pane
.children
.clone()
.into_iter()
.zip(new_dimensions.into_iter())
{
self.update_rectangle(conn, key, Some(dimensions)).await?;
}
}
}
RectangleContents::Client(client) => {
client
.frame
.configure(
conn,
ConfigureWindowParameters {
x: Some(dimensions.x.into()),
y: Some(dimensions.y.into()),
width: Some(dimensions.width.into()),
height: Some(dimensions.height.into()),
..Default::default()
},
self.focused.unwrap(),
)
.await?;
}
}
Ok(())
})
}
pub fn has_client(&self, win: Window) -> bool {
self.clients.contains_key(&win)
}
pub async fn remove_client<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
win: Window,
) -> Result<()> {
let client_key = *self
.clients
.get(&win)
.ok_or(XcrabError::ClientDoesntExist)?;
let client = self.rects.get(client_key).unwrap();
client.unwrap_client().frame.unframe(conn).await?;
let parent_key = client.parent;
let parent = self.rects.get_mut(parent_key).unwrap();
parent.unwrap_pane_mut().children.retain(|&v| v != client_key);
self.clients.remove(&win);
self.rects.remove(client_key);
if self.focused.unwrap() == win {
self.focused = self.clients.keys().copied().next();
self.update_focused(conn).await?;
}
self.update_rectangle(conn, parent_key, None).await?;
Ok(())
}
pub async fn destroy_focused_client<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
) -> Result<()> {
if let Some(focused) = self.focused {
let client_key = *self
.clients
.get(&focused)
.ok_or(XcrabError::ClientDoesntExist)?;
let frame = self
.rects
.get(client_key)
.unwrap()
.unwrap_client()
.frame;
self.remove_client(conn, focused).await?;
frame.kill_client(conn).await?;
Ok(())
} else {
Ok(())
}
}
pub async fn set_focus<Dpy: AsyncDisplay + ?Sized>(
&mut self,
conn: &mut Dpy,
win: Window,
) -> Result<()> {
let client_key = *self
.clients
.get(&win)
.ok_or(XcrabError::ClientDoesntExist)?;
self.focused = Some(win);
self.update_focused(conn).await?;
self.update_rectangle(
conn,
self.rects.get(client_key).unwrap().parent,
None,
)
.await?;
Ok(())
}
pub async fn get_focused(&self) -> Option<Window> {
self.focused
}
pub async fn get_framed_window(&self, window: Window) -> FramedWindow {
let focused_key = self.clients.get(&window).unwrap();
let focused = self.rects.get(*focused_key).unwrap();
let focused_frame = focused.unwrap_client().frame;
focused_frame
}
}
pub fn may_not_exist(res: breadx::Result) -> breadx::Result {
match res {
Err(BreadError::XProtocol { error_code: ErrorCode(3), .. }) => Ok(()),
v => v,
}
}
pub struct FramedWindow {
pub frame: Window,
pub win: Window,
}
#[automatically_derived]
impl ::core::fmt::Debug for FramedWindow {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(
f,
"FramedWindow",
"frame",
&self.frame,
"win",
&&self.win,
)
}
}
#[automatically_derived]
impl ::core::clone::Clone for FramedWindow {
#[inline]
fn clone(&self) -> FramedWindow {
let _: ::core::clone::AssertParamIsClone<Window>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for FramedWindow {}
impl FramedWindow {
async fn configure<Dpy: AsyncDisplay + ?Sized>(
self,
conn: &mut Dpy,
props: ConfigureWindowParameters,
focused_win: Window,
) -> Result<()> {
let inset = 2 * u32::from(CONFIG.border_size());
let width = props.width.map(|v| v - inset);
let height = props.height.map(|v| v - inset);
let focused = focused_win == self.win;
self.frame
.change_attributes_async(
conn,
WindowParameters {
border_pixel: Some(
if focused {
CONFIG.focused_color()
} else {
CONFIG.border_color()
},
),
..Default::default()
},
)
.await?;
self.frame
.configure_async(
conn,
ConfigureWindowParameters {
x: props.x,
y: props.y,
width,
height,
border_width: Some(CONFIG.border_size().into()),
..Default::default()
},
)
.await?;
may_not_exist(
self
.win
.configure_async(
conn,
ConfigureWindowParameters {
x: Some(-1),
y: Some(-1),
width,
height,
..Default::default()
},
)
.await,
)?;
Ok(())
}
async fn map<Dpy: AsyncDisplay + ?Sized>(
self,
conn: &mut Dpy,
) -> Result<()> {
may_not_exist(self.win.map_async(conn).await)?;
self.frame.map_async(conn).await?;
Ok(())
}
async fn unframe<Dpy: AsyncDisplay + ?Sized>(
self,
conn: &mut Dpy,
) -> Result<()> {
let root = conn.default_root();
self.frame.unmap_async(conn).await?;
may_not_exist(self.win.unmap_async(conn).await)?;
may_not_exist(self.win.reparent_async(conn, root, 0, 0).await)?;
may_not_exist(
self.win.change_save_set_async(conn, SetMode::Delete).await,
)?;
self.frame.free_async(conn).await?;
Ok(())
}
async fn kill_client<Dpy: AsyncDisplay + ?Sized>(
self,
conn: &mut Dpy,
) -> Result<()> {
struct ListOfAtom(Vec<Atom>);
impl AsByteSequence for ListOfAtom {
fn size(&self) -> usize {
::core::panicking::panic("not implemented")
}
fn as_bytes(&self, _: &mut [u8]) -> usize {
::core::panicking::panic("not implemented")
}
fn from_bytes(mut bytes: &[u8]) -> Option<(Self, usize)> {
let mut index = 0;
let mut vec = Vec::new();
while let Some((atom, index2)) = Atom::from_bytes(bytes) {
vec.push(atom);
index += index2;
bytes = &bytes[index2..];
}
Some((Self(vec), index))
}
}
fn as_u8_slice(data: &[u32]) -> &[u8] {
unsafe {
slice::from_raw_parts(
data.as_ptr().cast::<u8>(),
data.len().checked_mul(4).unwrap(),
)
}
}
let wm_protocols = conn
.intern_atom_immediate_async("WM_PROTOCOLS", true)
.await?;
if !(wm_protocols.xid != 0) {
::core::panicking::panic("assertion failed: wm_protocols.xid != 0")
}
let wm_delete_window = conn
.intern_atom_immediate_async("WM_DELETE_WINDOW", true)
.await?;
if !(wm_delete_window.xid != 0) {
::core::panicking::panic(
"assertion failed: wm_delete_window.xid != 0",
)
}
let prop = self
.win
.get_property_immediate_async::<
_,
ListOfAtom,
>(conn, wm_protocols, PropertyType::Atom, false)
.await?;
let protocols = prop.unwrap().0;
if protocols.contains(&wm_delete_window) {
let data = [wm_delete_window.xid, 0, 0, 0, 0];
let data_bytes = as_u8_slice(&data);
conn.send_event_async(
self.win,
EventMask::default(),
Event::ClientMessage(ClientMessageEvent {
event_type: 33,
format: 32,
sequence: 0,
window: self.win,
ty: wm_protocols,
data: ClientMessageData::from_bytes(data_bytes).unwrap().0,
}),
)
.await?;
} else {
self.win.free_async(conn).await?;
}
Ok(())
}
}
async fn frame<Dpy: AsyncDisplay + ?Sized>(
conn: &mut Dpy,
win: Window,
) -> Result<FramedWindow> {
let root = conn.default_root();
let geometry = win.geometry_immediate_async(conn).await?;
let frame = conn
.create_simple_window_async(
root,
geometry.x,
geometry.y,
geometry.width,
geometry.height,
CONFIG.border_size(),
CONFIG.border_color(),
0x00_00_00,
)
.await?;
frame
.set_event_mask_async(
conn,
EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY,
)
.await?;
win.set_event_mask_async(conn, EventMask::BUTTON_PRESS).await?;
may_not_exist(win.change_save_set_async(conn, SetMode::Insert).await)?;
may_not_exist(win.reparent_async(conn, frame, 0, 0).await)?;
Ok(FramedWindow { frame, win })
}
pub fn keymap(state: &mut KeyboardState) -> HashMap<Keysym, Keycode> {
let mut map: HashMap<Keysym, Keycode> = HashMap::new();
for keycode in 8..255_u8 {
let key = state.process_keycode(keycode, KeyButMask::default());
let keysyms = state.lookup_keysyms(keycode);
if key != None {
for keysym in keysyms {
map.insert(*keysym, keycode);
}
}
}
map
}
}
}
use x11::client::{may_not_exist, XcrabWindowManager};
#[non_exhaustive]
pub enum XcrabError {
#[error("breadx error: {0}")]
Bread(#[from] BreadError),
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("toml error: {0}")]
Toml(#[from] toml::de::Error),
#[error("env var error: {0}")]
Var(#[from] std::env::VarError),
#[error("client doesnt exist")]
ClientDoesntExist,
#[error("{0}")]
Custom(String),
}
#[allow(unused_qualifications)]
impl std::error::Error for XcrabError {
fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
use thiserror::__private::AsDynError;
#[allow(deprecated)]
match self {
XcrabError::Bread { 0: source, .. } => {
std::option::Option::Some(source.as_dyn_error())
}
XcrabError::Io { 0: source, .. } => {
std::option::Option::Some(source.as_dyn_error())
}
XcrabError::Toml { 0: source, .. } => {
std::option::Option::Some(source.as_dyn_error())
}
XcrabError::Var { 0: source, .. } => {
std::option::Option::Some(source.as_dyn_error())
}
XcrabError::ClientDoesntExist { .. } => std::option::Option::None,
XcrabError::Custom { .. } => std::option::Option::None,
}
}
}
#[allow(unused_qualifications)]
impl std::fmt::Display for XcrabError {
fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
#[allow(unused_imports)]
use thiserror::__private::{DisplayAsDisplay, PathAsDisplay};
#[allow(unused_variables, deprecated, clippy::used_underscore_binding)]
match self {
XcrabError::Bread(_0) => {
__formatter.write_fmt(format_args!("breadx error: {0}", _0.as_display()))
}
XcrabError::Io(_0) => {
__formatter.write_fmt(format_args!("io error: {0}", _0.as_display()))
}
XcrabError::Toml(_0) => {
__formatter.write_fmt(format_args!("toml error: {0}", _0.as_display()))
}
XcrabError::Var(_0) => {
__formatter
.write_fmt(format_args!("env var error: {0}", _0.as_display()))
}
XcrabError::ClientDoesntExist {} => {
__formatter.write_fmt(format_args!("client doesnt exist"))
}
XcrabError::Custom(_0) => {
__formatter.write_fmt(format_args!("{0}", _0.as_display()))
}
}
}
}
#[allow(unused_qualifications)]
impl std::convert::From<BreadError> for XcrabError {
#[allow(deprecated)]
fn from(source: BreadError) -> Self {
XcrabError::Bread { 0: source }
}
}
#[allow(unused_qualifications)]
impl std::convert::From<std::io::Error> for XcrabError {
#[allow(deprecated)]
fn from(source: std::io::Error) -> Self {
XcrabError::Io { 0: source }
}
}
#[allow(unused_qualifications)]
impl std::convert::From<toml::de::Error> for XcrabError {
#[allow(deprecated)]
fn from(source: toml::de::Error) -> Self {
XcrabError::Toml { 0: source }
}
}
#[allow(unused_qualifications)]
impl std::convert::From<std::env::VarError> for XcrabError {
#[allow(deprecated)]
fn from(source: std::env::VarError) -> Self {
XcrabError::Var { 0: source }
}
}
#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
pub struct CONFIG {
__private_field: (),
}
#[doc(hidden)]
pub static CONFIG: CONFIG = CONFIG { __private_field: () };
impl ::lazy_static::__Deref for CONFIG {
type Target = config::XcrabConfig;
fn deref(&self) -> &config::XcrabConfig {
#[inline(always)]
fn __static_ref_initialize() -> config::XcrabConfig {
config::load_file()
.unwrap_or_else(|e| {
{
::std::io::_print(
format_args!("[CONFIG] Error parsing config: {0}\n", e),
);
};
{
::std::io::_print(
format_args!("[CONFIG] Falling back to default config\n"),
);
};
config::XcrabConfig::default()
})
}
#[inline(always)]
fn __stability() -> &'static config::XcrabConfig {
static LAZY: ::lazy_static::lazy::Lazy<config::XcrabConfig> = ::lazy_static::lazy::Lazy::INIT;
LAZY.get(__static_ref_initialize)
}
__stability()
}
}
impl ::lazy_static::LazyStatic for CONFIG {
fn initialize(lazy: &Self) {
let _ = &**lazy;
}
}
impl Debug for XcrabError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(self, f)
}
}
type Result<T> = std::result::Result<T, XcrabError>;
fn main() -> Result<()> {
let body = async {
let mut conn = AsyncDisplayConnection::create_async(None, None).await?;
let root = conn.default_root();
root.set_event_mask_async(
&mut conn,
EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY
| EventMask::KEY_PRESS,
)
.await?;
let mut manager = XcrabWindowManager::new();
conn.grab_server_async().await?;
let top_level_windows = root
.query_tree_immediate_async(&mut conn)
.await?
.children;
for &win in top_level_windows.iter() {
let attrs = win.window_attributes_immediate_async(&mut conn).await?;
if !attrs.override_redirect && attrs.map_state == MapState::Viewable {
manager.add_client(&mut conn, win).await?;
}
}
conn.ungrab_server_async().await?;
let mut mask = ModMask::new(
false,
false,
true,
false,
false,
false,
false,
false,
false,
);
let mut keyboard_state = KeyboardState::new_async(&mut conn).await?;
let keymap = x11::client::keymap(&mut keyboard_state);
let mut request_key = *keymap
.get(&120)
.ok_or_else(|| {
XcrabError::Custom(
"At least one letter could not be found in the keymap".to_string(),
)
})?;
for &binds in CONFIG.binds.keys() {
for keysym in 97..122_u32 {
let keycode = keymap
.get(&keysym)
.ok_or_else(|| {
XcrabError::Custom(
"At least one letter could not be found in the keymap"
.to_string(),
)
})?;
let iter_char = keyboard_state
.process_keycode(*keycode, KeyButMask::default())
.ok_or_else(|| {
XcrabError::Custom(
"The keycode returned from the keymap could not be processed"
.to_string(),
)
})?
.as_char()
.ok_or_else(|| {
XcrabError::Custom(
"The processed Key could not be cast as a char".to_string(),
)
})?;
if iter_char == binds.key {
request_key = *keycode;
mask.inner = binds.mods.inner;
}
}
}
mask.set_Two(true);
conn.exchange_request_async(GrabKeyRequest {
req_type: 33,
owner_events: false,
length: 4,
grab_window: root,
modifiers: mask,
key: request_key,
pointer_mode: GrabMode::Async,
keyboard_mode: GrabMode::Async,
})
.await?;
mask.set_Two(false);
conn.exchange_request_async(GrabKeyRequest {
req_type: 33,
owner_events: false,
length: 4,
grab_window: root,
modifiers: mask,
key: request_key,
pointer_mode: GrabMode::Async,
keyboard_mode: GrabMode::Async,
})
.await?;
let (send, mut recv) = unbounded_channel();
let (result_send, result_recv) = unbounded_channel();
tokio::spawn(
msg_listener::listener_task(
CONFIG.msg.clone().unwrap_or_default().socket_path,
send,
result_recv,
),
);
loop {
{
#[doc(hidden)]
mod __tokio_select_util {
pub(super) enum Out<_0, _1> {
_0(_0),
_1(_1),
Disabled,
}
pub(super) type Mask = u8;
}
use ::tokio::macros::support::Future;
use ::tokio::macros::support::Pin;
use ::tokio::macros::support::Poll::{Ready, Pending};
const BRANCHES: u32 = 2;
let mut disabled: __tokio_select_util::Mask = Default::default();
if !true {
let mask: __tokio_select_util::Mask = 1 << 0;
disabled |= mask;
}
if !true {
let mask: __tokio_select_util::Mask = 1 << 1;
disabled |= mask;
}
let mut output = {
let mut futures = (recv.recv(), conn.wait_for_event_async());
::tokio::macros::support::poll_fn(|cx| {
let mut is_pending = false;
let start = 0;
for i in 0..BRANCHES {
let branch;
#[allow(clippy::modulo_one)]
{
branch = (start + i) % BRANCHES;
}
match branch {
#[allow(unreachable_code)]
0 => {
let mask = 1 << branch;
if disabled & mask == mask {
continue;
}
let (fut, ..) = &mut futures;
let mut fut = unsafe { Pin::new_unchecked(fut) };
let out = match Future::poll(fut, cx) {
Ready(out) => out,
Pending => {
is_pending = true;
continue;
}
};
disabled |= mask;
#[allow(unused_variables)] #[allow(unused_mut)]
match &out {
Some(s) => {}
_ => continue,
}
return Ready(__tokio_select_util::Out::_0(out));
}
#[allow(unreachable_code)]
1 => {
let mask = 1 << branch;
if disabled & mask == mask {
continue;
}
let (_, fut, ..) = &mut futures;
let mut fut = unsafe { Pin::new_unchecked(fut) };
let out = match Future::poll(fut, cx) {
Ready(out) => out,
Pending => {
is_pending = true;
continue;
}
};
disabled |= mask;
#[allow(unused_variables)] #[allow(unused_mut)]
match &out {
Ok(ev) => {}
_ => continue,
}
return Ready(__tokio_select_util::Out::_1(out));
}
_ => {
::core::panicking::unreachable_display(
&"reaching this means there probably is an off by one bug",
)
}
}
}
if is_pending {
Pending
} else {
Ready(__tokio_select_util::Out::Disabled)
}
})
.await
};
match output {
__tokio_select_util::Out::_0(Some(s)) => {
msg_listener::on_recv(s, &mut manager, &mut conn, &result_send)
.await?
}
__tokio_select_util::Out::_1(Ok(ev)) => {
process_event(
ev,
&mut manager,
&mut conn,
root,
&mut keyboard_state,
)
.await?
}
__tokio_select_util::Out::Disabled => {
::std::rt::begin_panic(
"all branches are disabled and there is no else branch",
)
}
_ => ::core::panicking::unreachable_display(&"failed to match bind"),
}
}
}
};
#[allow(clippy::expect_used, clippy::diverging_sub_expression)]
{
return tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.expect("Failed building the Runtime")
.block_on(body);
}
}
#[allow(clippy::too_many_lines)]
async fn process_event<Dpy: AsyncDisplay + ?Sized>(
ev: Event,
manager: &mut XcrabWindowManager,
conn: &mut Dpy,
root: Window,
keyboard_state: &mut KeyboardState,
) -> Result<()> {
match ev {
Event::MapRequest(ev) => {
manager.add_client(conn, ev.window).await?;
}
Event::ConfigureRequest(ev) => {
let mut params = ConfigureWindowParameters {
x: Some(ev.x.into()),
y: Some(ev.y.into()),
width: Some(ev.width.into()),
height: Some(ev.height.into()),
border_width: Some(ev.border_width.into()),
sibling: None,
stack_mode: Some(ev.stack_mode),
};
if manager.has_client(ev.window) {
params.x = None;
params.y = None;
params.width = None;
params.height = None;
}
may_not_exist(ev.window.configure_async(conn, params).await)?;
}
Event::UnmapNotify(ev) => {
if ev.event != root && manager.has_client(ev.window) {
manager.remove_client(conn, ev.window).await?;
}
}
Event::ButtonPress(ev) => {
if ev.detail == 1 {
manager.set_focus(conn, ev.event).await?;
}
}
Event::KeyPress(ev) => {
if let Some(k) = keyboard_state.process_keycode(ev.detail, ev.state) {
if let Some(c) = k.as_char() {
for (&bind, action) in &CONFIG.binds {
if bind.key == c {
action.eval(manager, conn).await?;
}
}
}
}
}
_ => {}
}
Ok(())
}