Somehow, the fix in the previous commit didn't work, it seems that
sometimes epoll() doesn't trigger, even if there is more data in
sys.stdin. I'm sure I'm doing something horribly wrong here.
Anyhow, as a quick fix, check for the open bracket to be sure to not
buffer the first event too long.
Re-enable the possibility to define custom mouse actions by binding
commands to "<alias|module>.<left-click|right-click|...>". These
commands are then executed as shell commands.
fixes#30
Instead of having a thread that runs in the background continuously,
spawn a new one for every update interval. That speeds up the tests
quite a lot.
see #23
Show RTT measured by ICMP echo request/replies for a given host.
For that to work correctly, change the "full_text" callback for a widget
so that the widget itself is also passed as argument in the callback
method. That actually makes a lot of sense, since the widget can now be
used as a repository of state information.
see #23
Quite a lot of modules use the "if higher X -> critical, if higher Y ->
warning" idiom now, so extracted that into a common function for reuse.
see #23
Until now, as soon as a widget registered *any* callback, the default
callbacks (e.g. scroll up/down to go to next/previous workspace) didn't
work anymore, as there was a better match for the general registration
(even though not for the button).
To fix this, merge the callback registration into a flat registration,
where a key is calculated from the ID of the registrar and the
registered button.
see #23
If the computer runs on AC, display that instead of showing "100%" in
the status.
Also, if reading the charging status fails for some reason (except the
computer being on AC), go into critical state and display "n/a".
see #23
Allow modules to define aliases. This replaces the symlink mechanism
that was in place previously, because it was a bit ugly (and confused
code climate).
see #23
Make input thread non-blocking by using select(). This increases the CPU
utilization a bit (depending on the timeout), but makes the thread exit
cleanly, even if an exception is thrown in the main thread.
see #23
If a widget exists for an interface that is not there anymore (i.e. a
tunnel interface that has been removed, or a USB device that has been
unplugged), remove that widget from the list.
see #23
Re-add the NIC module with all its functionality (hopefully...).
This introduces a new concept: Instead of having separate queries for
critical and warning (which really are just another set of states), a
module can now return a list of states for each widget. All the state
information is then merged together into a single theme. So, for
instance, the NIC module can return a state saying "critical -
wlan-down", which applies the theme information for both "critical" and
"wlan-down".
see #23
I cannot get the min_width property to work right now, so in order to
fix the width of the CPU widget, pad the utilization to 3 digits (so
that even 100% aligns nicely).
see #23
The cpu module now has cpu.warning and cpu.critical thresholds. If the
CPU utilization is higher than any of those values, the widget's state
changes to warning or critical, respectively.
see #23
Create infrastructure for input event handling and add i3bar event
processing. For each event, callbacks can be registered in the input
module.
Modules and widgets both identify themselves using a unique ID (the
module name for modules, a generated UUID for the widgets). This ID is
then used for registering the callbacks. This is possible since both
widgets and modules are statically allocated & do not change their IDs.
Callback actions can be either callable Python objects (in which case
the event is passed as parameter), or strings, in which case the string
is interpreted as a shell command.
see #23
Each widget can now return a state using the method "state()". This
string is then used to look up a theme information which is used instead
of the default or module theme, if found.
see #23
Add customized separators:
* The default separators are automatically disabled if custom separators
are used (to "just" disable the default, use empty custom separators)
* Use previous background color as their background color and the
current background color as foreground color
* Allow the separator-block-width to be configured
see #23
Allow a theme to define a "cycle" of attributes that are cycled through
on a widget-per-widget basis (e.g. for alternating the widget
background). These cycles take precedence over the default values, but
can be overridden by module-specific theme instructions.
see #23
Make the format string of the datetime module configurable using the new
parameter() method in the module.
Also, restructured the setting of the config information a bit so that
the parameter() method can be used in the constructor of a module.
see #23
User can now use -p <key>=<value> to pass configuration parameters to
modules. For this, the module gets a "parameter()" method. Parameter
keys are in the format <name>.<key> where <name> is the name of the
loaded module. This is either the name of the module itself (e.g. "cpu")
or its alias, if the user specified it, for example:
bumblebee-status -m cpu -p cpu.warning=90
vs.
bumblebee-status -m cpu:test -p test.warning=90
see #23
Add an interface that allows arbitrary objects to store/retrieve
arbitrary key/value pairs. This will be used for different purposes in
the future:
* Config class(es) can store user-defined parameters for modules
* Widgets can store state
* ???
see #23
Add a helper function that lists all existing modules and modify the CPU
module test so that it now generically iterates all available modules
and tests their widgets.
see #23
Allow module-specific theme information to overload "default"
configuration. I.e. it is now possible to have specific prefix or
postfix configurations for different modules. The module name is derived
for each widget from the module (__module__) from which it was
instantiated.
see #23
Allow sub-themes ("iconsets") to be merged into the "main" theme. That
way, effectively, it's possible to define colors and icons in separate
JSON files.
see #23
Until now, widgets were re-created during each iteration. For multiple,
reasons, using static widget objects is much easier, so instead of
creating new widgets continuously, modules now create the widgets during
instantiation and get the list of widgets passed as parameter whenever
an update occurs. During the update, they can still manipulate the
widget list by removing and adding elements as needed.
Advantages:
* Less memory fragmentation (fewer (de)allocations)
* Easier event management (widgets now have static IDs)
* Easier module code (widget contents can simply be the result of a
callback)
see #23
Add custom exceptions and add error handling to the engine's module
loading logic. I.e. when a non-existent module is loaded, an exception
is thrown now.
see #23
Add basic drawing of widgets. Each module instance returns a list of
widgets using the widgets() method which is then forwarded to the draw()
method of the configured output.
see #23
Allow the user to provide aliases when loading a module multiple times
so that the modules can be differentiated (e.g. for passing parameters
to a module).
see #23
This is going to be a bit more comprehensive than anticipated. In order
to cleanly refactor the core and the engine, basically start from
scratch with the implementation.
Goals:
* Test coverage
* Maintain backwards compatibility with module interface as much as
possible (but still make modules easier to code)
* Simplicity
see #23
Cycled widget styles (such as the battery charging style) were broken
until now. The reason for this: They maintain state that represents the
current cycle position (i.e. what is the current icon that is being
displayed), but that is done in a way that uses repr() on the widget
object.
Since the widget objects are re-created each time the bar is drawn, this
is a deeply flawed design.
Instead, use the instance() of the widget for now.
Hide alias concept for modules in the engine. That way, the individual
modules never get to know about whether a module has been aliased or
not.
see #23
"nic.exclude" is now a parameter that can be used to have a custom list
of excluded interface prefixes. Multiple prefixes should be separated by
a comma.
fixes#26
When receiving a "nop" (None) command, skip it. Otherwise, an exception
is thrown and input processing stops.
Also, remove the "communicate()" call to *not* wait until a process has
finished until resuming input processing. Otherwise, whenever an
external program (pavucontrol, nautilius, ...) is started, any further
input processing is stalled until the program has been closed again.
fixes#24
Whenever the language is changed outside the bar, update the bar
accordingly. Also, when a new language is used, automatically append it
to the list of available languages.
User can now specify a list of languages as parameter (pipe-separated
list). Variants can also be specified by separating language and variant
with a :
For instance: -p layout.lang="us|rs:latin"
Left click moves on to the next language, right click to the previous.
Right now, there are the following caveats:
* The first entry in the list must be the language used when the bar
starts
* kxbd changes outside the bar are not picked up automatically
This one is a bit tricky:
* Clicking on an active xrandr output will disable it
* Clicking on a disabled xrandr output will enable it -> if
it is a left-click, it will put it as the left-most display
if it is a right-click, as the right-most display
Also, it will reload the i3 bars (using a script that allows
you to write custom pieces of an i3 configuration that is applied
conditionally depending on the screens you have).
It goes like this:
* Base config is in ~/.i3/config.template
* Output-specific config is in ~/.i3/config.<screen name>
* Output-specific config when other screens are also active is in
~/.i3/config.<screen>-<other-screens-in-alphabetic-order>
For instance:
$ ls ~/.i3
config.template
config.eDP1 -> will be applied to eDP1 (always)
config.VGA1-eDP1 -> will be applied to VGA1, if eDP1 is also active
config.VGA1 -> will be applied to VGA1 (if eDP1 is inactive)
fixes#19
This modules shows attached displays and their states (on or off).
Future versions of this module will order the icons by the relative
order of the screens (left-to-right) and will allow switching monitors
on and off.
see #19
Add code that allows themes to be merged (i.e. if certain elements are
not present in a theme, another theme can be "overlaid" to add missing
elements).
Effectively, this is used to create the logical concept of an "icon
theme", which is loaded after the main theme. So, the main theme can
define colors, and the icon theme fills in any missing elements
(practically, all the icons in the form of prefixes and suffixes).
Icon sets are defined in a theme using the "icons" directive, which
should be an array.
see #17
Add the possibility to specify a list of commands to be added as
callbacks. Commands will be executed one after the other, waiting for
the previous command to finish execution.
Due to a bug, when the destination was unreachable, the checking thread
would terminate, effectively keeping the widget stuck in "unreachable"
mode.
Now, enable recovery by keeping the thread running even if the target is
not reachable for some time.
Add controls that allow the user to switch to the next and previous song
in cmus, toggle shuffle and repeat. Pause/play is toggled by clicking on
the song title itself.
fixes#5
Allow the user to use all tags read by cmus (cmus-remote -Q|grep ^tag)
as part of the displayed data (plus the special 'tags' "duration" and
"position").
This callback just makes it really hard to see for the user what is
going on. The alias the user provides should *always* match the
instance, so that it can be used in a meaningful way in the click
action, for example (otherwise, something like "nautilus {instance}"
gets really hard to interpret.
This is now much nicer implemented to address issue #3. A user can now
have a configuration parameter mapped to a module instance (via the
module name or the instance name) with the value "left-click",
"right-click", etc., like this:
-m disk:home -p home.left-click="nautilus {instance}"
Big oversight in my previous commits: Widgets need to be able to have
specific configurations (i.e. the path for different instances of the
"disk" module has to be different).
To account for that, it is now possible to assign an "alias" to a module
instance using ":" (for example: -m "disk:home"). This alias is then
used for the configuration parameter resolution automatically, for
example:
-m disk:home -p home.path=/home
As a consequence, parameter names in the module code are now relative to
the module, which means: shorter!
Repeatedly querying the interface type the way I'm doing right now
results in "too many files open" pretty quickly. Obviously, it's a bit
of a concern that I am leaking a file descriptor somewhere, but for now,
the quickfix is to cache the type (it shouldn't change, anyhow).
All callback from a widget into a module (e.g. for retrieving the status
or the criticality state) now get a widget passed. This has the purpose
of allowing a module to store state/widget specific data somewhere. This
way, for instance, it is possible to store the interface name as part of
the widget, thus making it possible to show the status of the correct
interface.
Allow the user to specify arbitrary configuration parameters from the
commandline and evaluate those in the modules (and elsewhere). Re-enable
the CPU module as a first showcase of this functionality.
Allow theme entries to be lists that are then iterated. For this
purpose, extend the Config class so that it can serve as generic store
for data items. That makes it easy to centralize code used for rotation
etc. in a single place.
Yet another bug in the DNF module - really a troublesome one. Only call
the dnf updateinfo every interval, not every second. That significantly
reduces CPU load.
Due to name-clashing of the datetime module's "time" alias, time.sleep
didn't work (as it was looked up from the i3bumblebee module),
consequently, the DNF poll thread exited.
While at it, "beautify" the thread cancelling a bit by waiting until
the main thread is not running anymore.
* cpu+memory: Open "gnome-system-monitor"
* disk: Open nautilus
* pulseaudio: Mute/unmute, open "pavucontrol" on right-click, raise/lower
volume on mouse wheel up/down
Pass the "output" object to the modules' constructor to allow them to
define their own callbacks.
Any user-provided callbacks take precedence and override those of the
module.
The i3 output now has a separate thread that continuously monitors stdin
for incoming click events. The generic output class also has methods for
registering callbacks (as commands). For now, by default, scroll events
will be used to emulate the next/previous workspace.
Add a module that periodically (by default, once every 30min) calls
"dnf updateinfo" and evaluates the results to report the number of
bugfixes, enhancements, etc.
If there's either too many pending updates, or at least one security
update, the module goes critical.
Add a module that retrieve mute status and volume (left, right, mono)
from pulseaudio. Unfortunately, this module is really, really hacky. It
invokes "pactl" multiple times to get the status and does some ugly
parsing on the output.
Overall, this is pretty brittle and prone to failure, but as I was not
able to find a decent pulseaudio library for Python... Probably, I
haven't searched hard enough, cannot believe such a thing does not
exist.
Add a new module "disk" that takes an optional parameter (the path) and
displays free & total disk space, along with the usage percentage.
Also, added Tunnel/VPN support to the themeing of the "net" module.
First, cache lookups were bugged... Second, the output needs to call
data() first, everything else later.
This is a bit nasty, and I'll consider re-visiting this, but right now,
I don't see any other way, given that modules can now be iterated.