Compare commits

...

16 Commits

Author SHA1 Message Date
Cadey Ratio 858949745e updates
Signed-off-by: Christine Dodrill <me@christine.website>
2021-06-09 09:39:52 -04:00
Cadey Ratio 398cd96934 omg colors
Signed-off-by: Christine Dodrill <me@christine.website>
2021-01-30 10:34:31 -05:00
Cadey Ratio 8501c8b61d giga oops
Signed-off-by: Christine Dodrill <me@christine.website>
2021-01-30 10:21:13 -05:00
Cadey Ratio 50d62d1283 oops
Signed-off-by: Christine Dodrill <me@christine.website>
2021-01-30 10:18:30 -05:00
Cadey Ratio ae305313eb pilno lahoi sway
Signed-off-by: Christine Dodrill <me@christine.website>
2021-01-30 10:11:30 -05:00
Cadey Ratio 6095468e76 Update '.drone.yml'
continuous-integration/drone/push Build is passing Details
2020-11-06 14:31:16 +00:00
Cadey Ratio e92842da33 Update 'default.nix'
continuous-integration/drone/push Build is failing Details
2020-11-06 14:30:48 +00:00
Cadey Ratio 364efb280c really disable openssl
continuous-integration/drone/push Build is passing Details
2020-10-28 08:38:29 -04:00
Cadey Ratio 6e3d49beb2 rustls
continuous-integration/drone/push Build is passing Details
2020-10-28 08:19:45 -04:00
Cadey Ratio 3cb50f1c35 0.3.0
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is passing Details
2020-10-28 08:12:29 -04:00
Cadey Ratio 19dd028c07 remove x11 crate 2020-10-28 08:12:08 -04:00
Cadey Ratio c78fb3dcb5 more slow
continuous-integration/drone/push Build is passing Details
2020-08-25 16:06:15 -04:00
Cadey Ratio 310c018d0c fix lag 2020-08-25 16:04:46 -04:00
Cadey Ratio 3de2d10f90 v0.2.1
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2020-04-10 07:20:26 -04:00
Cadey Ratio 722a99c8d9 use anyhow all over
continuous-integration/drone/push Build is failing Details
2020-04-10 07:18:51 -04:00
Cadey Ratio b4d3cfe960 use anyhow 2020-04-10 07:12:09 -04:00
14 changed files with 474 additions and 960 deletions

View File

@ -2,6 +2,6 @@ kind: pipeline
name: zbasu
steps:
- commands:
- "nix-build ./cabytcini.nix"
- "nix-build"
image: "monacoremo/nix:2020-04-05-05f09348-circleci"
name: zbasu le sampla

5
CHANGELOG.md Normal file
View File

@ -0,0 +1,5 @@
# Changelog
## 0.3.0
- Rewrite using async rust

920
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package]
name = "cabytcini"
version = "0.2.0"
version = "0.3.0"
authors = ["Christine Dodrill <me@christine.website>"]
edition = "2018"
license = "MIT"
@ -8,18 +8,12 @@ license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
chrono = "0.4"
log = "0.4"
env_logger = "0.7"
serde = { version = "1", features = [ "derive" ] }
log = "0.4"
serde_json = "1"
serde = { version = "1", features = [ "derive" ] }
toml = "0.5"
xdg = "2.2"
[dependencies.reqwest]
version = "0.10"
features = [ "blocking", "json" ]
[dependencies.x11]
features = ["xlib"]
version = "2.18.2"
ureq = { version = "2", features = ["json", "charset"] }

View File

@ -5,10 +5,10 @@
"homepage": "",
"owner": "nmattia",
"repo": "naersk",
"rev": "1dd63230066a93c61ab7a66934eb0aae3f1a3613",
"sha256": "1xn8m62ypg13jh4zf101qmfa6gy8cl923fgwvk9c33m573h3k154",
"rev": "e8061169e1495871b56be97c5c51d310fae01374",
"sha256": "0683bdn7nvd63ziy09vm43iwpis4fdsj2hyk14hksz7igwrsy2g3",
"type": "tarball",
"url": "https://github.com/nmattia/naersk/archive/1dd63230066a93c61ab7a66934eb0aae3f1a3613.tar.gz",
"url": "https://github.com/nmattia/naersk/archive/e8061169e1495871b56be97c5c51d310fae01374.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"niv": {
@ -17,22 +17,22 @@
"homepage": "https://github.com/nmattia/niv",
"owner": "nmattia",
"repo": "niv",
"rev": "f73bf8d584148677b01859677a63191c31911eae",
"sha256": "0jlmrx633jvqrqlyhlzpvdrnim128gc81q5psz2lpp2af8p8q9qs",
"rev": "527494090f7075ed5e3aa15ef7093846e5e25d52",
"sha256": "1hahf0i0iix1iyzaaq5a7rbgyfm3xjcfl69lm1b5mas1p8vdimih",
"type": "tarball",
"url": "https://github.com/nmattia/niv/archive/f73bf8d584148677b01859677a63191c31911eae.tar.gz",
"url": "https://github.com/nmattia/niv/archive/527494090f7075ed5e3aa15ef7093846e5e25d52.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixpkgs": {
"branch": "nixos-20.03",
"branch": "nixpkgs-unstable",
"description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",
"homepage": "https://github.com/NixOS/nixpkgs",
"owner": "NixOS",
"repo": "nixpkgs-channels",
"rev": "0bb35152be895abfd1fc743b42f1c4e56ae71906",
"sha256": "0mydmhr1fm5l0p668wx5wlk3six7k3n56sz41fv0h9zms0lqszf9",
"rev": "502845c3e31ef3de0e424f3fcb09217df2ce6df6",
"sha256": "0fcqpsy6y7dgn0y0wgpa56gsg0b0p8avlpjrd79fp4mp9bl18nda",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs-channels/archive/0bb35152be895abfd1fc743b42f1c4e56ae71906.tar.gz",
"url": "https://github.com/NixOS/nixpkgs-channels/archive/502845c3e31ef3de0e424f3fcb09217df2ce6df6.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

View File

@ -6,52 +6,63 @@ let
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: spec:
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; }
else
pkgs.fetchurl { inherit (spec) url sha256; };
fetch_file = pkgs: name: spec:
let
name' = sanitizeName name + "-src";
in
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
else
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
fetch_tarball = pkgs: spec:
if spec.builtin or true then
builtins_fetchTarball { inherit (spec) url sha256; }
else
pkgs.fetchzip { inherit (spec) url sha256; };
fetch_tarball = pkgs: name: spec:
let
name' = sanitizeName name + "-src";
in
if spec.builtin or true then
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
else
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
fetch_git = spec:
builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
fetch_git = name: spec:
let
ref =
if spec ? ref then spec.ref else
if spec ? branch then "refs/heads/${spec.branch}" else
if spec ? tag then "refs/tags/${spec.tag}" else
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
in
builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
fetch_builtin-tarball = spec:
builtins.trace
''
WARNING:
The niv type "builtin-tarball" will soon be deprecated. You should
instead use `builtin = true`.
fetch_local = spec: spec.path;
$ niv modify <package> -a type=tarball -a builtin=true
''
builtins_fetchTarball { inherit (spec) url sha256; };
fetch_builtin-tarball = name: throw
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=tarball -a builtin=true'';
fetch_builtin-url = spec:
builtins.trace
''
WARNING:
The niv type "builtin-url" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=file -a builtin=true
''
(builtins_fetchurl { inherit (spec) url sha256; });
fetch_builtin-url = name: throw
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=file -a builtin=true'';
#
# Various helpers
#
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
sanitizeName = name:
(
concatMapStrings (s: if builtins.isList s then "-" else s)
(
builtins.split "[^[:alnum:]+._?=-]+"
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
)
);
# The set of packages used when specs are fetched using non-builtins.
mkPkgs = sources:
mkPkgs = sources: system:
let
sourcesNixpkgs =
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {};
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
in
@ -71,14 +82,27 @@ let
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs spec
else if spec.type == "tarball" then fetch_tarball pkgs spec
else if spec.type == "git" then fetch_git spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec
else if spec.type == "builtin-url" then fetch_builtin-url spec
else if spec.type == "file" then fetch_file pkgs name spec
else if spec.type == "tarball" then fetch_tarball pkgs name spec
else if spec.type == "git" then fetch_git name spec
else if spec.type == "local" then fetch_local spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
else if spec.type == "builtin-url" then fetch_builtin-url name
else
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# If the environment variable NIV_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
replace = name: drv:
let
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
in
if ersatz == "" then drv else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
@ -87,23 +111,37 @@ let
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
concatMapStrings = f: list: concatStrings (map f list);
concatStrings = builtins.concatStringsSep "";
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
optionalAttrs = cond: as: if cond then as else {};
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, sha256 }@attrs:
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball { inherit url; }
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, sha256 }@attrs:
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchurl;
in
if lessThan nixVersion "1.12" then
fetchurl { inherit url; }
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchurl attrs;
@ -115,14 +153,15 @@ let
then abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = fetch config.pkgs name spec; }
spec // { outPath = replace name (fetch config.pkgs name spec); }
) config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? ./sources.json
, sources ? builtins.fromJSON (builtins.readFile sourcesFile)
, pkgs ? mkPkgs sources
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
, system ? builtins.currentSystem
, pkgs ? mkPkgs sources system
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
@ -130,5 +169,6 @@ let
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
};
in
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

77
src/bin/cabytcinysuhei.rs Normal file
View File

@ -0,0 +1,77 @@
use anyhow::Result;
use cabytcini::*;
use chrono::prelude::*;
use std::{
sync::{Arc, Mutex},
thread, time,
};
const UPDATE_FREQUENCY: u64 = 15000;
fn main() -> Result<()> {
env_logger::init();
println!(r#"{{ "version": 1 }}"#);
println!("[[]");
let st: State = State::init();
let mtst = Arc::new(Mutex::new(st));
let cfg = config::load()?;
// start front thread
{
let mtst = mtst.clone();
let cfg = cfg.clone();
thread::spawn(move || front::update(mtst, cfg));
}
// start weather thread
{
let mtst = mtst.clone();
let cfg = cfg.clone();
thread::spawn(move || weather::update(mtst, cfg));
}
thread::sleep(time::Duration::from_millis(750));
loop {
{
let data = mtst.lock().unwrap();
let mut blocks: Vec<Block> = vec![Block {
full_text: data.front.clone(),
color: match data.front.as_str() {
"Cadey" => Some("#F86AF3".to_string()),
"Nicole" => Some("#C79DD7".to_string()),
"Jessie" => Some("#97871A".to_string()),
"Ashe" => Some("#458588".to_string()),
"Sephie" => Some("#D79921".to_string()),
"Mai" => Some("#D65D0E".to_string()),
_ => None,
},
}];
if let Some(datni) = &data.weather {
blocks.push(Block {
full_text: format!(
"{} {} / {} {}",
datni.currently.temperature,
datni.currently.summary,
datni.daily.data[0].temperature_high,
datni.daily.data[0].temperature_low
),
color: None,
})
}
blocks.push(Block {
full_text: Local::now().format("%H:%M M%m %-d %a").to_string(),
color: None,
});
println!(",{}", serde_json::to_string(&blocks)?);
}
let so_often = time::Duration::from_millis(UPDATE_FREQUENCY);
thread::sleep(so_often);
}
}

View File

@ -1,29 +1,26 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::{
fs::File,
io::{Read, Result, Write},
io::{Read, Write},
};
use xdg::*;
#[derive(Deserialize, Serialize, Debug, Clone)]
pub(crate) struct Config {
pub struct Config {
pub(crate) front_url: String,
pub(crate) weather_url: String,
}
pub(crate) fn load() -> Result<Config> {
pub fn load() -> Result<Config> {
let xdg_dirs =
BaseDirectories::with_prefix("cabytcini").expect("pu djica lo nu finti lei datnyveiste");
let config_path = xdg_dirs
.place_config_file("gaftercu'a.toml")
.expect("pu djica lo nu le datnyveiste be lo gaftercu'a zvati");
let config_path = xdg_dirs.place_config_file("gaftercu'a.toml")?;
match File::open(&config_path) {
Ok(mut fin) => {
let mut datni = String::new();
fin.read_to_string(&mut datni)
.expect("pu djica lo nu tcidu le sfaile");
let cfg: Config =
toml::from_str(datni.as_str()).expect("pu djica lo nu jimpe lo sfaile");
fin.read_to_string(&mut datni)?;
let cfg: Config = toml::from_str(datni.as_str())?;
Ok(cfg)
}

View File

@ -4,12 +4,15 @@ use std::{thread, time};
const FIVE_MINUTES: u64 = 60 * 5;
pub(crate) fn update(st: MTState, cfg: Config) {
pub fn update(st: MTState, cfg: Config) {
loop {
match reqwest::blocking::get(&cfg.front_url) {
match ureq::get(&cfg.front_url)
.set("User-Agent", crate::APP_USER_AGENT)
.call()
{
Ok(who) => {
let mut data = st.lock().unwrap();
let who = who.text().unwrap().trim().to_string();
let who = who.into_string().unwrap().trim().to_string();
if who != data.front {
data.front = who;
info!("new front: {}", data.front);

90
src/lib.rs Normal file
View File

@ -0,0 +1,90 @@
#[macro_use]
extern crate log;
use chrono::prelude::*;
use serde::Serialize;
use std::{
fmt,
sync::{Arc, Mutex},
};
use xsetroot::XSetRoot;
pub mod config;
pub mod front;
pub mod weather;
pub mod xsetroot;
pub static APP_USER_AGENT: &str = concat!(
env!("CARGO_PKG_NAME"),
"/",
env!("CARGO_PKG_VERSION"),
" +https://tulpa.dev/cadey/cabytcini",
);
pub type MTState = Arc<Mutex<State>>;
pub struct State {
pub msg: String,
pub front: String,
pub weather: Option<weather::Root>,
}
#[derive(Serialize, Default)]
pub struct Block {
pub full_text: String,
pub color: Option<String>,
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl State {
pub fn init() -> State {
State {
msg: "".to_string(),
front: "".to_string(),
weather: None,
}
}
pub fn to_string(&self) -> String {
let now = Local::now().format("%H:%M M%m %-d %a");
let mut msg = String::new();
if self.msg != "" {
msg.push_str(format!("{} | ", self.msg).as_str());
}
if self.front != "" {
msg.push_str(format!("{} | ", self.front).as_str());
}
match &self.weather {
Some(datni) => msg.push_str(
format!(
"{} {} / {} {} | ",
datni.currently.temperature,
datni.currently.summary,
datni.daily.data[0].temperature_high,
datni.daily.data[0].temperature_low
)
.as_str(),
),
None => {}
};
msg.push_str(format!("{}", now).as_str());
msg
}
pub fn xsetroot(&self) {
let xsr = XSetRoot::init().expect("xsetroot to initialize");
if let Err(why) = xsr.render(self.to_string()) {
error!("error setting root window title: {:?}", why);
}
}
}

View File

@ -1,29 +1,16 @@
mod config;
mod front;
mod weather;
mod xsetroot;
use chrono::prelude::*;
use anyhow::Result;
use log::*;
use std::{
fmt,
io::{prelude::*, BufReader},
net::Shutdown,
os::unix::net::{UnixListener, UnixStream},
sync::{Arc, Mutex},
thread, time,
};
use xsetroot::XSetRoot;
// Name your user agent after your app?
pub static APP_USER_AGENT: &str = concat!(
env!("CARGO_PKG_NAME"),
"/",
env!("CARGO_PKG_VERSION"),
" +https://tulpa.dev/cadey/cabytcini",
);
use cabytcini::*;
pub(crate) type MTState = Arc<Mutex<State>>;
pub type MTState = Arc<Mutex<State>>;
fn handle_client(stream: UnixStream, st: MTState) {
let mut rdr = BufReader::new(&stream);
@ -37,7 +24,7 @@ fn handle_client(stream: UnixStream, st: MTState) {
stream.shutdown(Shutdown::Both).expect("socket to close");
}
const UPDATE_FREQUENCY: u64 = 250;
const UPDATE_FREQUENCY: u64 = 15000;
fn update_every_so_often(st: MTState) {
loop {
@ -46,14 +33,14 @@ fn update_every_so_often(st: MTState) {
{
let data = st.lock().unwrap();
data.show();
data.xsetroot();
}
}
}
fn main() -> std::io::Result<()> {
fn main() -> Result<()> {
let st: State = State::init();
st.show();
st.xsetroot();
let mtst = Arc::new(Mutex::new(st));
env_logger::init();
let cfg = config::load()?;
@ -87,63 +74,10 @@ fn main() -> std::io::Result<()> {
thread::spawn(move || handle_client(stream, mtst));
}
Err(err) => {
error!("unix listener error: {:?}", err);
break;
return Err(err.into());
}
}
}
Ok(())
}
pub(crate) struct State {
msg: String,
front: String,
weather: Option<weather::Root>,
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl State {
fn init() -> State {
State {
msg: "".to_string(),
front: "".to_string(),
weather: None,
}
}
pub(crate) fn show(&self) {
let now = Local::now().format("%H:%M M%m %-d %a");
let xsr = XSetRoot::init();
let mut msg = String::new();
if self.msg != "" {
msg.push_str(format!("{} | ", self.msg).as_str());
}
if self.front != "" {
msg.push_str(format!("{} | ", self.front).as_str());
}
match &self.weather {
Some(datni) => msg.push_str(format!(
"{} {} / {} {} | ",
datni.currently.temperature,
datni.currently.summary,
datni.daily.data[0].temperature_high,
datni.daily.data[0].temperature_low
).as_str()),
None => {}
};
msg.push_str(format!("{}", now).as_str());
xsr.render(msg);
}
}

View File

@ -1,5 +1,5 @@
use crate::{config::Config, MTState};
use reqwest::blocking::*;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::{thread, time};
@ -40,14 +40,16 @@ pub struct Daum {
const UPDATE_FREQUENCY: u64 = 15 * 60; // 15 minutes
fn get(cfg: &Config) -> reqwest::Result<Root> {
let client = Client::builder().user_agent(crate::APP_USER_AGENT).build()?;
let now: Root = client.get(&cfg.weather_url).send()?.json()?;
fn get(cfg: &Config) -> Result<Root> {
let now: Root = ureq::get(&cfg.weather_url)
.set("User-Agent", crate::APP_USER_AGENT)
.call()?
.into_json()?;
Ok(now)
}
pub(crate) fn update(st: MTState, cfg: Config) {
pub fn update(st: MTState, cfg: Config) {
loop {
match get(&cfg) {
Ok(datni) => {

View File

@ -1,53 +1,17 @@
#![allow(unsafe_code)]
use std::ffi::CString;
use std::os::raw::c_char;
use std::ptr;
use x11::xlib;
use anyhow::Result;
use std::process::Command;
pub(crate) struct XSetRoot {
display: *mut xlib::Display,
root_window: xlib::Window,
}
pub struct XSetRoot;
impl XSetRoot {
pub(crate) fn init() -> Self {
unsafe {
let display = xlib::XOpenDisplay(ptr::null());
if display.is_null() {
panic!("cannot open display");
}
let screen = xlib::XDefaultScreen(display);
let root_window = xlib::XRootWindow(display, screen);
Self {
display,
root_window,
}
}
pub fn init() -> Result<Self> {
Ok(Self {})
}
pub(crate) fn render(&self, text: String) {
let status_c = CString::new(text).expect("status text could not be converted to CString");
unsafe {
xlib::XStoreName(
self.display,
self.root_window,
status_c.as_ptr() as *mut c_char,
);
xlib::XFlush(self.display);
}
}
}
impl Drop for XSetRoot {
fn drop(&mut self) {
unsafe {
xlib::XCloseDisplay(self.display);
}
pub fn render(&self, text: String) -> Result<()> {
Command::new("xsetroot").arg("-name").arg(text).output()?;
Ok(())
}
}