mjkillough / cnx Goto Github PK
View Code? Open in Web Editor NEWA simple X11 status bar for use with simple WMs.
License: MIT License
A simple X11 status bar for use with simple WMs.
License: MIT License
Hi! Hoping to try this project out. It might be unmaintained, in which case please ignore me.
I'm unable to compile cnx on recent Arch because of (fundamentally) bugs in the older bindgen when processing headers from glibc 2.39. This will affect the other distros eventually.
The compilation failure is in iwlib-sys:
error: failed to run custom build command for `iwlib_sys v0.1.0`
Caused by:
process didn't exit successfully: `/home/cbiffle/src/cnx/target/debug/build/iwlib_sys-fae758f3245ddce5/build-script-build` (exit status: 101)
--- stdout
cargo:rustc-link-lib=iw
cargo:rerun-if-changed=wrapper.h
--- stderr
thread 'main' panicked at /home/cbiffle/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-0.53.3/src/ir/context.rs:894:9:
"__atomic_wide_counter_struct_(unnamed_at_/usr/include/bits/atomic_wide_counter_h_28_3)" is not a valid Ident
This appears to be due to bindgen 0.53 parsing header files wrong. (I agree with the error message -- that last line is certainly not a valid ident!) Something glibc has started doing between whatever version you're testing on, and version 2.39, has confused it.
It appears that iwlib-sys in git has been updated to use bindgen 0.65, which fixes the problem. However, it also doesn't seem to have made a release in about a year. I see that this project and iwlib-sys have some committers in common, so you might be able to fix this by either making an iwlib-sys release and bumping your dependency, or depending on its git repo directly.
However, doing either is going to require either removing the dependency on the (apparently unmaintained) sioctl package, or updating it, too, to use a more modern bindgen. Otherwise, they conflict and Cargo can't resolve the dependency graph.
By editing cnx's Cargo.toml to depend on iwlib from git, and removing the use of sioctl, I was able to get it to build.
So the window title just stays the same instead of going blank. Is this the expected behavior or is my setup bugged?
Greetings mejo
Is there a specific reason, why the rust toolchain is fixed to 1.50.0
?
It compiles well with 1.56.1
How about 'cnx' given that most of it has been developed in Chiang Mai?
Currently hard-coded and changed often while debugging. I'm sick of having to commit to change it back to the bottom before I install a new version on my system!
Pretty sure I have all the dependencies you listed.
RUST_BACKTRACE=1 cargo build
Compiling sndio-sys v0.0.1
error: failed to run custom build command for `sndio-sys v0.0.1`
Caused by:
process didn't exit successfully: `/home/jamie/.local/share/cnx/target/debug/build/sndio-sys-97395fbed55da30d/build-script-build` (exit code: 101)
--- stdout
cargo:rustc-link-lib=sndio
cargo:rerun-if-changed=wrapper.h
--- stderr
wrapper.h:1:10: fatal error: 'sndio.h' file not found
wrapper.h:1:10: fatal error: 'sndio.h' file not found, err: true
thread 'main' panicked at 'Unable to generate bindings: ()', /home/jamie/.cargo/registry/src/github.com-1ecc6299db9ec823/sndio-sys-0.0.1/build.rs:8:20
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:78
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:59
4: core::fmt::write
at src/libcore/fmt/mod.rs:1063
5: std::io::Write::write_fmt
at src/libstd/io/mod.rs:1426
6: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:62
7: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:49
8: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:204
9: std::panicking::default_hook
at src/libstd/panicking.rs:224
10: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:470
11: rust_begin_unwind
at src/libstd/panicking.rs:378
12: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
13: core::option::expect_none_failed
at src/libcore/option.rs:1211
14: core::result::Result<T,E>::expect
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libcore/result.rs:961
15: build_script_build::main
at ./build.rs:8
16: std::rt::lang_start::{{closure}}
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/rt.rs:67
17: std::rt::lang_start_internal::{{closure}}
at src/libstd/rt.rs:52
18: std::panicking::try::do_call
at src/libstd/panicking.rs:303
19: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:86
20: std::panicking::try
at src/libstd/panicking.rs:281
21: std::panic::catch_unwind
at src/libstd/panic.rs:394
22: std::rt::lang_start_internal
at src/libstd/rt.rs:51
23: std::rt::lang_start
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/rt.rs:67
24: main
25: __libc_start_main
26: _start
As this will be running all the time on my laptop system, I would like it to be as efficient as possible. This ticket tracks doing some non-scientific profiling under average-ish conditions to see how it compares to my previous setup (QTile).
It'd be interesting to use this in order to measure improvements from #16 and #18.
It's me again!
I'm currently coding a pager for LeftWM, which takes a monitor name, stream the result of letwm-state
and allow to have a more correct pager for multi monitor than EWMH: mainly on which monitor has the focus.
As the other issue, would you be interested in merging it in cnx-contrib
?
can a systray be added as a widget, i miss it from polybar, and in my opinion it is the projects biggest short coming when it comes to widgets.
... with some useful contents.
Hey ! Nice project, just getting started with it!
I have this use case, with 2 monitors, where I want a bar on each monitor.
Currently, it just stretches across the 2 monitors.
I have a small patch that add 2 Option
s to the Bar::new
, namely width
and x_offset
.
I feel it's just a quickhack ๐
height
is not useful AFAIK, and y_offset
makes not much sense (well it could maybe, not sure).
I was thinking of maybe adding some with_x_offset
, with_width
to the Bar
struct, wdyt?
We're expecting people will write their own main()
to configure how the bar runs/which widgets are used, so we should try make it as simple as possible.
I'm trying to launch cnx with https://github.com/sminez/penrose
Here is my code:
use cnx::Cnx;
use penrose::{
builtin::{
actions::{exit, log_current_state, modify_with, send_layout_message, spawn},
layout::{
messages::{ExpandMain, IncMain, ShrinkMain},
transformers::{Gaps, ReflectHorizontal, ReserveTop},
MainAndStack,
},
},
core::{
bindings::{parse_keybindings_with_xmodmap, KeyEventHandler},
layout::LayoutStack,
Config, WindowManager,
},
extensions::hooks::add_ewmh_hooks,
map, stack,
x11rb::RustConn,
};
use std::{collections::HashMap, thread, time::Duration};
use tracing::log::debug;
use tracing_subscriber::{self, prelude::*, EnvFilter};
fn raw_key_bindings() -> HashMap<String, Box<dyn KeyEventHandler<RustConn>>> {
let mut raw_bindings = map! {
// map_keys: |k: &str| format!("C-{k}");
map_keys: |k: &str| k.to_owned();
"M-j" => modify_with(|cs| cs.focus_down()),
"M-k" => modify_with(|cs| cs.focus_up()),
"M-S-j" => modify_with(|cs| cs.swap_down()),
"M-S-k" => modify_with(|cs| cs.swap_up()),
"M-S-q" => modify_with(|cs| cs.kill_focused()),
"M-Tab" => modify_with(|cs| cs.toggle_tag()),
"M-bracketright" => modify_with(|cs| cs.next_screen()),
"M-bracketleft" => modify_with(|cs| cs.previous_screen()),
"M-grave" => modify_with(|cs| cs.next_layout()),
"M-S-grave" => modify_with(|cs| cs.previous_layout()),
"M-Up" => send_layout_message(|| IncMain(1)),
"M-Down" => send_layout_message(|| IncMain(-1)),
"M-Right" => send_layout_message(|| ExpandMain),
"M-Left" => send_layout_message(|| ShrinkMain),
"M-semicolon" => spawn("dmenu_run"),
"M-S-s" => log_current_state(),
"M-Return" => spawn("st"),
"M-A-Escape" => exit(),
};
for tag in &["1", "2", "3", "4", "5", "6", "7", "8", "9"] {
raw_bindings.extend([
(
format!("M-{tag}"),
// change_workspace(tag.to_string()),
modify_with(move |client_set| {
// change_workspace::<RustConn>(tag.to_string());
client_set.focus_tag(tag);
}),
),
(
format!("M-S-{tag}"),
modify_with(move |client_set| client_set.move_focused_to_tag(tag)),
),
]);
}
raw_bindings
}
fn layouts() -> LayoutStack {
let max_main = 1;
let ratio = 0.6;
let ratio_step = 0.1;
let outer_px = 5;
let inner_px = 5;
let top_px = 18;
stack!(
MainAndStack::side(max_main, ratio, ratio_step),
ReflectHorizontal::wrap(MainAndStack::side(max_main, ratio, ratio_step)),
MainAndStack::bottom(max_main, ratio, ratio_step)
)
.map(|layout| ReserveTop::wrap(Gaps::wrap(layout, outer_px, inner_px), top_px))
}
fn main() {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.finish()
.init();
debug!("=====STARTING=======");
let wm_handle = thread::spawn(|| {
let config = add_ewmh_hooks(Config {
default_layouts: layouts(),
..Config::default()
});
let conn = RustConn::new().unwrap();
let key_bindings = parse_keybindings_with_xmodmap(raw_key_bindings()).unwrap();
let wm = WindowManager::new(config, key_bindings, HashMap::new(), conn).unwrap();
wm.run().unwrap();
});
let cnx_handle = thread::spawn(|| {
let attr = cnx::text::Attributes {
font: cnx::text::Font::new("Consolas"),
fg_color: cnx::text::Color::blue(),
bg_color: Some(cnx::text::Color::red()),
padding: cnx::text::Padding::new(0.0, 0.0, 0.0, 0.0),
};
let mut cnx = Cnx::new(cnx::Position::Bottom);
let time_template = Some("<span foreground=\"#808080\">[</span>%d-%m-%Y %a %I:%M %p<span foreground=\"#808080\">]</span>".into());
cnx.add_widget(cnx::widgets::Clock::new(attr.clone(), time_template));
cnx.add_widget(cnx::widgets::ActiveWindowTitle::new(attr.clone()));
cnx.run().unwrap();
});
wm_handle.join();
debug!("wm_handle is done");
cnx_handle.join();
debug!("cnx_handle is done");
}
In this case cnx doesn't launch properly (see small top rectangle):
But it works only if I run it as another process or without spawning penrose thread.
This is one of the final widget I would like to have in cnx.
Looking briefly at the crates, I believe I could easily use procfs to get the appropriate data: https://crates.io/crates/procfs
I've been looking for a status bar that's positioned along the left or right edge of the screen, with text rotated 90 degrees. It seems like a good way to save precious vertical space on tiny laptop screens, but I haven't found any status bars with this option. So writing / modifying one myself seems like the thing to do. I'm here at cnx because rust, and because it has the most readable source of any status bar I've looked at.
So, how do you feel about having Position::Left
and Position::Right
options for a vertical statusbar? Do you have any advice on the best way to implement it, without making a mess of your existing code?
I just spent a few minutes messing around with Position::Left
, and it seems simple to get the struts and the surface in more or less the right place. The text rendering is more complicated, though, and I have no experience with cairo. Maybe all the text can be rendered normally, using the screen height as the text "width", and then the whole cairo context can be rotate 90 degrees? I tried adding context.rotate(PI / 2.)
, and it rotates the background rectangle, but there's no text visible.
Would allow others to use it and customize which widgets are used, etc.
xcb has some major changes and it would be good to catch up.
Unfortunately, we are currently blocked on this issue: meh/rust-xcb-util#22
top
shows the processes are still running. Perhaps we're accidentally using XDestroyWindow
(or XCB equiv) when it is expecting WM_DELETE
?
Any wayland support soon?
I think that is _NET_WM_WINDOW_TYPE=_NET_WM_WINDOW_TYPE_DOCK
and _NET_WM_STRUT
/_NET_WM_STRUT_PARTIAL
as per the EWMH spec.
The value displayed by the volume widget doesn't update but remains as the same value when starting the bar.
That is if the volume is 70% when starting the bar, the value displayed by the widget remains 70% even if I increase or decrease the volume.
Os - Garuda Linux Soaring
The docs state that cnx reads battery info from /sys/class/power_supply/BAT0/
but my device doesn't seem to have this directory. Instead a /sys/class/power_supply/BAT1/
directory exists with all the battery info.
So when I use:
cnx_add_widget!(cnx, Battery::new(&cnx, attr.clone(), Color::red()));
an error is thrown:
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
Could not load value from battery status file: charge_full
We currently have a Widget
trait that provides a fn stream(self) -> Box<Stream<...>>
method. As we use widgets as Box<Widget>
(as we want trait objects), we actually have two levels of indirection.
Could we get rid of one of them by saying a Widget
is anything that implements the right type of Stream<...>
?
... avoids unnecessary wake-ups.
If the window title is really long, it overflows into the other widgets.
Should we also truncate non-stretch widgets?
They're currently updated every second on a timer, but this is inefficient. We should listen for changes to the specific properties on the root window.
... suggesting it can't parse the command output. I suspect the degree symbol.
It'd be nice if the Clock widget could sleep until it knows its output is going to change. I don't think we can use the generic timer_widget!()
for this.
I see that a related issue was open already but it has been closed: #32
I'm planning to try out cnx and possibly make it as my status bar. But unfortunately it seem the master doesn't seem to be working with Linux.
From looking further it seems to be because of sioctl
which is introduced in the volume widget. Would you be willing it to make it behind an optional feature instead: https://doc.rust-lang.org/cargo/reference/features.html
I can also volunteer to send a PR for the same. :-)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.