Eww - Widgets for everyone!
Eww (ElKowar's Wacky Widgets, pronounced with sufficient amounts of disgust) is a widget system made in Rust, which lets you create your own widgets similarly to how you can in AwesomeWM. The key difference: It is independent of your window manager!
Configured in yuck and themed using CSS, it is easy to customize and provides all the flexibility you need!
How to install Eww
Prerequisites
- rustc
- cargo
Rather than with your system package manager, I strongly recommend installing it using rustup.
Additionally, eww requires some dynamic libraries to be available on your system. The exact names of the packages that provide these may differ depending on your distribution. The following list of package names should work for arch linux:
Packages
- gtk3 (libgdk-3, libgtk-3)
- gtk-layer-shell (only on Wayland)
- pango (libpango)
- gdk-pixbuf2 (libgdk_pixbuf-2)
- libdbusmenu-gtk3
- cairo (libcairo, libcairo-gobject)
- glib2 (libgio, libglib-2, libgobject-2)
- gcc-libs (libgcc)
- glibc
(Note that you will most likely need the -devel variants of your distro's packages to be able to compile eww.)
Building
Once you have the prerequisites ready, you're ready to install and build eww.
First clone the repo:
git clone https://github.com/elkowar/eww
cd eww
Then build:
cargo build --release --no-default-features --features x11
NOTE: When you're on Wayland, build with:
cargo build --release --no-default-features --features=wayland
Running eww
Once you've built it you can now run it by entering:
cd target/release
Then make the Eww binary executable:
chmod +x ./eww
Then to run it, enter:
./eww daemon
./eww open <window_name>
Writing your eww configuration
(For a list of all built-in widgets (i.e. box
, label
, button
), see Widget Documentation.)
Eww is configured using its own language called yuck
.
Using yuck, you declare the structure and content of your widgets, the geometry, position, and behavior of any windows,
as well as any state and data that will be used in your widgets.
Yuck is based around S-expressions, which you may know from lisp-like languages.
If you're using vim, you can make use of yuck.vim for editor support.
If you're using VSCode, you can get syntax highlighting and formatting from yuck-vscode.
It is also recommended to use parinfer,
which makes working with S-expressions delightfully easy!
Additionally, any styles are defined in CSS or SCSS (which is mostly just slightly improved CSS syntax).
While eww supports a significant portion of the CSS you know from the web,
not everything is supported, as eww relies on GTK's own CSS engine.
Notably, some animation features are unsupported,
as well as most layout-related CSS properties such as flexbox, float
, absolute position or width
/height
.
To get started, you'll need to create two files: eww.yuck
and eww.scss
(or eww.css
, if you prefer).
These files must be placed under $XDG_CONFIG_HOME/eww
(this is most likely ~/.config/eww
).
Now that those files are created, you can start writing your first widget!
Creating your first window
Firstly, you will need to create a top-level window. Here, you configure things such as the name, position, geometry, and content of your window.
Let's look at an example window definition:
(defwindow example
:monitor 0
:geometry (geometry :x "0%"
:y "20px"
:width "90%"
:height "30px"
:anchor "top center")
:stacking "fg"
:reserve (struts :distance "40px" :side "top")
:windowtype "dock"
:wm-ignore false
"example content")
Here, we are defining a window named example
, which we then define a set of properties for. Additionally, we set the content of the window to be the text "example content"
.
You can now open your first window by running eww open example
! Glorious!
defwindow
-properties
Property | Description |
---|---|
monitor | Which monitor this window should be displayed on. See below for details. |
geometry | Geometry of the window. |
monitor
-property
This field can be:
- the string
<primary>
, in which case eww tries to identify the primary display (which may fail, especially on wayland) - an integer, declaring the monitor index
- the name of the monitor
- a string containing a JSON-array of monitor matchers, such as:
'["<primary>", "HDMI-A-1", "PHL 345B1C", 0]'
. Eww will try to find a match in order, allowing you to specify fallbacks.
geometry
-properties
Property | Description |
---|---|
x , y | Position of the window. Values may be provided in px or % . Will be relative to anchor . |
width , height | Width and height of the window. Values may be provided in px or % . |
anchor | Anchor-point of the window. Either center or combinations of top , center , bottom and left , center , right . |
Depending on if you are using X11 or Wayland, some additional properties exist:
X11
Property | Description |
---|---|
stacking | Where the window should appear in the stack. Possible values: fg , bg . |
wm-ignore | Whether the window manager should ignore this window. This is useful for dashboard-style widgets that don't need to interact with other windows at all. Note that this makes some of the other properties not have any effect. Either true or false . |
reserve | Specify how the window manager should make space for your window. This is useful for bars, which should not overlap any other windows. |
windowtype | Specify what type of window this is. This will be used by your window manager to determine how it should handle your window. Possible values: normal , dock , toolbar , dialog , desktop . Default: dock if reserve is specified, normal otherwise. |
Wayland
Property | Description |
---|---|
stacking | Where the window should appear in the stack. Possible values: fg , bg , overlay , bottom . |
exclusive | Whether the compositor should reserve space for the window automatically. Either true or false . |
focusable | Whether the window should be able to be focused. This is necessary for any widgets that use the keyboard to work. Possible values: none , exclusive and ondemand . |
namespace | Set the wayland layersurface namespace eww uses. Accepts a string value. |
Your first widget
While our bar is already looking great, it's a bit boring. Thus, let's add some actual content!
(defwidget greeter [?text name]
(box :orientation "horizontal"
:halign "center"
text
(button :onclick "notify-send 'Hello' 'Hello, ${name}'"
"Greet")))
To show this, let's replace the text in our window definition with a call to this new widget:
(defwindow example
; ... values omitted
(greeter :text "Say hello!"
:name "Tim"))
There is a lot going on here, so let's step through this.
We are creating a widget named greeter
. This widget takes two attributes, called text
and name
.
The declaration ?text
specifies that the text
-attribute is optional, and can thus be left out. In that case,
its value will be the empty string ""
.
The name
attribute must be provided.
Now we declare the body of our widget. We make use of a box
, which we set a couple attributes of.
We need this box
, as a widget definition can only ever contain a single widget - otherwise,
eww would not know if it should align them vertically or horizontally, how it should space them, and so on.
Thus, we wrap multiple children in a box
.
This box then contains a reference to the provided attribute text
, as well as a button.
In that button's onclick
attribute, we refer to the provided name
using string-interpolation syntax: "${name}"
.
This allows us to easily refer to any variables within strings.
In fact, there is a lot more you can do within ${...}
- more on that in the chapter about the expression language.
To then use our widget, we call it just like we would use any other built-in widget and provide the required attributes.
As you may have noticed, we are using a couple predefined widgets here. These are all listed and explained in the widgets chapter.
Rendering children in your widgets
As your configuration grows, you might want to improve the structure of your config by factoring out functionality into basic reusable widgets.
Eww allows you to create custom wrapper widgets that can themselves take children, just like some of the built-in widgets like box
or button
can.
For this, use the children
placeholder:
(defwidget labeled-container [name]
(box :class "container"
name
(children)))
Now you can use this widget as expected:
(labeled-container :name "foo"
(button :onclick "notify-send hey ho"
"click me"))
You can also create more complex structure by referring to specific children with the nth
-attribute:
(defwidget two-boxes []
(box
(box :class "first" (children :nth 0))
(box :class "second" (children :nth 1))))
Adding dynamic content
Now that you feel sufficiently greeted by your bar, you may realize that showing data like the time and date might be even more useful than having a button that greets you.
To implement dynamic content in your widgets, you make use of variables.
These user-defined variables are globally available from all of your widgets. Whenever the variable changes, the value in the widget will update!
There are four different types of variables: basic, polling, listening, and a set of builtin "magic" variables.
Basic variables (defvar
)
(defvar foo "initial value")
This is the simplest type of variable.
Basic variables don't ever change automatically.
Instead, you explicitly update them by calling eww like so: eww update foo="new value"
.
This is useful if you have values that change very rarely, or may change as a result of some external script you wrote.
They may also be useful to have buttons within eww change what is shown within your widget, by setting attributes like onclick
to run eww update
.
Polling variables (defpoll
)
(defvar time-visible false) ; for :run-while property of below variable
; when this turns true, the polling starts and
; var gets updated with given interval
(defpoll time :interval "1s"
:initial "initial-value" ; optional, defaults to poll at startup
:run-while time-visible ; optional, defaults to 'true'
`date +%H:%M:%S`)
A polling variable is a variable which runs a provided shell-script repeatedly, in a given interval.
This may be the most commonly used type of variable. They are useful to access any quickly retrieved value repeatedly, and thus are the perfect choice for showing your time, date, as well as other bits of information such as pending package updates, weather, and battery level.
You can also specify an initial-value. This should prevent eww from waiting for the result of a given command during startup, thus making the startup time faster.
Listening variables (deflisten
)
(deflisten foo :initial "whatever"
`tail -F /tmp/some_file`)
Listening variables might be the most confusing of the bunch.
A listening variable runs a script once, and reads its output continously.
Whenever the script outputs a new line, the value will be updated to that new line.
In the example given above, the value of foo
will start out as "whatever"
, and will change whenever a new line is appended to /tmp/some_file
.
These are particularly useful when you want to apply changes instantaneously when an operation happens if you have a script that can monitor some value on its own. Volume, brightness, workspaces that get added/removed at runtime, monitoring currently focused desktop/tag, etc. are the most common usecases of this type of variable. These are particularly efficient and should be preffered if possible.
For example, the command xprop -spy -root _NET_CURRENT_DESKTOP
writes the currently focused desktop whenever it changes.
Another example usecase is monitoring the currently playing song with playerctl: playerctl --follow metadata --format {{title}}
.
Built-in "magic" variables
In addition to defining your own variables, eww provides some values for you to use out of the box. These include values such as your CPU and RAM usage. These mostly contain their data as JSON, which you can then get using the json access syntax. All available magic variables are listed here.
Dynamically generated widgets with literal
In some cases, you want to not only change the text, value, or color of a widget dynamically, but instead want to generate an entire widget structure dynamically. This is necessary if you want to display lists of things (for example notifications) where the amount is not necessarily known, or if you want to change the widget structure in some other, more complex way.
For this, you can make use of one of eww's most powerful features: the literal
widget.
(defvar variable_containing_yuck
"(box (button 'foo') (button 'bar'))")
; Then, inside your widget, use:
(literal :content variable_containing_yuck)
Here, you specify the content of your literal by providing it a string (most likely stored in a variable) which contains a single yuck widget tree. Eww then reads the provided value and renders the resulting widget. Whenever it changes, the widget will be rerendered.
Note that this is not all that efficient. Make sure to only use literal
when necessary!
Using window arguments and IDs
In some cases you may want to use the same window configuration for multiple widgets, e.g. for multiple windows. This is where arguments and ids come in.
Window ID
Firstly let us start off with ids. An id can be specified in the open
command
with --id
, by default the id will be set to the name of the window
configuration. These ids allow you to spawn multiple of the same windows. So
for example you can do:
eww open my_bar --screen 0 --id primary
eww open my_bar --screen 1 --id secondary
When using open-many
you can follow the structure below. Again if no id is
given, the id will default to the name of the window configuration.
eww open-many my_config:primary my_config:secondary
You may notice with this we didn't set screen
, this is set through the
--arg
system, please see below for more information.
Window Arguments
However this may not be enough and you want to have slight changes for each of these bars, e.g. having a different class for 1080p displays vs 4k or having spawning the window in a different size or location. This is where the arguments come in.
Please note these arguments are CONSTANT and so cannot be update after the window has been opened.
Defining arguments in a window is the exact same as in a widget so you can have:
(defwindow my_bar [arg1 ?arg2]
:geometry (geometry
:x "0%"
:y "6px"
:width "100%"
:height { arg1 == "small" ? "30px" : "40px" }
:anchor "top center")
:stacking "bg"
:windowtype "dock"
:reserve (struts :distance "50px" :side "top")
(my_widget :arg2 arg2))
Here we have two arguments, arg1
and arg2
(an optional parameter).
Once we have these parameters, when opening a new window, we must specify them
(unless they are optional, like arg2
), but how? Well, we use the --arg
option when running the open
command:
eww open my_bar --id primary --arg arg1=some_value --arg arg2=another_value
With the open-many
it looks like this:
# Please note that `--arg` option must be given after all the windows names
eww open-many my_bar:primary --arg primary:arg1=some_value --arg primary:arg2=another_value
Using this method you can define screen
, anchor
, pos
, size
inside the
args for each window and it will act like giving --screen
, --anchor
etc. in
the open
command.
So, now you know the basics, I shall introduce you to some of these "special"
parameters, which are set slightly differently. However these can all be
overridden by the --arg
option.
id
- Ifid
is included in the argument list, it will be set to the id specified by--id
or will be set to the name of the config. This can be used when closing the current window through eww commands.screen
- Ifscreen
is specified it will be set to the value given by--screen
, so you can use this in other widgets to access screen specific information.
Further insight into args in open-many
Now due to the system behind processing the open-many
--arg
option you
don't have to specify an id for each argument. If you do not, that argument
will be applied across all windows e.g.
eww open-many my_bar:primary my_bar:secondary --arg gui_size="small"
This will mean the config is the same throughout the bars.
Furthermore if you didn't specify an id for the window, you can still set args specifically for that window - following the idea that the id will be set to the window configuration if not given - by just using the name of the window configuration e.g.
eww open-many my_primary_bar --arg my_primary_bar:screen=0
Generating a list of widgets from JSON using for
If you want to display a list of values, you can use the for
-Element to fill a container with a list of elements generated from a JSON-array.
(defvar my-json "[1, 2, 3]")
; Then, inside your widget, you can use
(box
(for entry in my-json
(button :onclick "notify-send 'click' 'button ${entry}'"
entry)))
This can be useful in many situations, for example when generating a workspace list from a JSON representation of your workspaces.
In many cases, this can be used instead of literal
, and should most likely be preferred in those cases.
To see how to declare and use more advanced data structures, check out the data structures example.
Splitting up your configuration
As time passes, your configuration might grow larger and larger. Luckily, you can easily split up your configuration into multiple files!
There are two options to achieve this:
Using include
(include "./path/to/your/file.yuck")
A single yuck file may import the contents of any other yuck file. For this, make use of the include
directive.
Using a separate eww configuration directory
If you want to separate different widgets even further, you can create a new eww config folder anywhere else.
Then, you can tell eww to use that configuration directory by passing every command the --config /path/to/your/config/dir
flag.
Make sure to actually include this in all your eww
calls, including eww kill
, eww logs
, etc.
This launches a separate instance of the eww daemon that has separate logs and state from your main eww configuration.
Simple expression language
Yuck includes a small expression language that can be used to run several operations on your data. This can be used to show different values depending on certain conditions, do mathematic operations, and even access values within JSON-structures.
These expressions can be placed anywhere within your configuration inside { ... }
,
as well as within strings, inside string-interpolation blocks ("foo ${ ... } bar"
).
Example
(box
"Some math: ${12 + foo * 10}"
(button :class {button_active ? "active" : "inactive"}
:onclick "toggle_thing"
{button_active ? "disable" : "enable"}))
Features
Supported currently are the following features:
- simple mathematical operations (
+
,-
,*
,/
,%
) - comparisons (
==
,!=
,>
,<
,<=
,>=
) - boolean operations (
||
,&&
,!
) - regex match operator (
=~
)- Rust regex style, left hand is regex, right hand is string
- ex: workspace.name =~ '^special:.+$'
- elvis operator (
?:
)- if the left side is
""
or a JSONnull
, then returns the right side, otherwise evaluates to the left side.
- if the left side is
- Safe Access operator (
?.
) or (?.[index]
)- if the left side is an empty string or a JSON
null
, then returnnull
. Otherwise, attempt to index. Note that indexing an empty JSON string ('""'
) is an error. - This can still cause an error to occur if the left hand side exists but is
not an object or an array.
(
Number
orString
).
- if the left side is an empty string or a JSON
- conditionals (
condition ? 'value' : 'other value'
) - numbers, strings, booleans and variable references (
12
,'hi'
,true
,some_variable
) - json access (
object.field
,array[12]
,object["field"]
)- for this, the object/array value needs to refer to a variable that contains a valid json string.
- some function calls:
round(number, decimal_digits)
: Round a number to the given amount of decimalssin(number)
,cos(number)
,tan(number)
,cot(number)
: Calculate the trigonometric value of a given number in radiansmin(a, b)
,max(a, b)
: Get the smaller or bigger number out of two given numberspowi(num, n)
,powf(num, n)
: Raise numbernum
to powern
.powi
expectsn
to be of typei32
degtorad(number)
: Converts a number from degrees to radiansradtodeg(number)
: Converts a number from radians to degreesreplace(string, regex, replacement)
: Replace matches of a given regex in a stringsearch(string, regex)
: Search for a given regex in a string (returns array)matches(string, regex)
: check if a given string matches a given regex (returns bool)captures(string, regex)
: Get the captures of a given regex in a string (returns array)strlength(value)
: Gets the length of the stringsubstring(string, start, length)
: Return a substring of given length starting at the given index
arraylength(value)
: Gets the length of the arrayobjectlength(value)
: Gets the amount of entries in the objectjq(value, jq_filter_string)
: run a jq style command on a json value. (Uses jaq internally).jq(value, jq_filter_string, args)
: Emulate command line flags for jq, see the docs on invoking jq for details. Invalid flags are silently ignored. Currently supported flags:"r"
: If the result is a string, it won't be formatted as a JSON string. The equivalent jq flag is--raw-output
.
get_env(string)
: Gets the specified enviroment variableformattime(unix_timestamp, format_str, timezone)
: Gets the time in a given format from UNIX timestamp. Check chrono's documentation for more information about format string and chrono-tz's documentation for available time zones.formattime(unix_timestamp, format_str)
: Gets the time in a given format from UNIX timestamp. Same as otherformattime
, but does not accept timezone. Instead, it uses system's local timezone. Check chrono's documentation for more information about format string.
GTK
Gtk-theming
Eww is styled in GTK CSS.
You can use Vanilla CSS
or SCSS
to make theming even easier. The latter is compiled into CSS for you.
If you don't know any way to style something check out the GTK CSS Overview wiki,
the GTK CSS Properties Overview wiki ,
or use the GTK-Debugger.
If you have NO clue about how to do CSS, check out some online guides or tutorials.
SCSS is very close to CSS, so if you know CSS you'll have no problem learning SCSS.
GTK-Debugger
The debugger can be used for a lot of things, especially if something doesn't work or isn't styled right.
To open the GTK debugger, simply run
eww inspector
If a style or something similar doesn't work, you can click on the icon in the top left to select the thing that isn't being styled correctly.
Then you can click on the drop down menu in the top right corner and select CSS Nodes. Here you will see everything about styling it, CSS Properties, and how it's structured.
Magic variables
These are variables that are always there, without you having to import them.
The delay between all the updating variables except EWW_TIME
is 2s, for EWW_TIME
it is 1s.
EWW_TEMPS
Heat of the components in degree Celsius
Structure
{ <name>: temperature }
EWW_RAM
Information on ram and swap usage in bytes.
Structure
{ total_mem, free_mem, total_swap, free_swap, available_mem, used_mem, used_mem_perc }
EWW_DISK
Information on on all mounted partitions (Might report inaccurately on some filesystems, like btrfs and zfs) Example: {EWW_DISK["/"]}
Structure
{ <mount_point>: { name, total, free, used, used_perc } }
EWW_BATTERY
Battery capacity in percent of the main battery
Structure
{ <name>: { capacity, status } }
EWW_CPU
Information on the CPU cores: frequency and usage (No MacOS support)
Structure
{ cores: [{ core, freq, usage }], avg }
EWW_NET
Bytes up/down on all interfaces
Structure
{ <name>: { up, down } }
EWW_TIME
the current UNIX timestamp
EWW_CONFIG_DIR
Path to the eww configuration of the current process
EWW_CMD
eww command running in the current configuration, useful in event handlers. I.e.: :onclick "${EWW_CMD} update foo=bar"
EWW_EXECUTABLE
Full path of the eww executable
Widgets
widget
these properties apply to all widgets, and can be used anywhere!
Properties
class
:string
css class namevalign
:string
how to align this vertically. possible values: "fill", "baseline", "center", "start", "end"halign
:string
how to align this horizontally. possible values: "fill", "baseline", "center", "start", "end"vexpand
:bool
should this container expand vertically. Default: false.hexpand
:bool
should this widget expand horizontally. Default: false.width
:int
width of this element. note that this can not restrict the size if the contents stretch itheight
:int
height of this element. note that this can not restrict the size if the contents stretch itactive
:bool
If this widget can be interacted withtooltip
:string
tooltip text (on hover)visible
:bool
visibility of the widgetstyle
:string
inline scss style applied to the widgetcss
:string
scss code applied to the widget, i.e.:button {color: red;}
combo-box-text
A combo box allowing the user to choose between several items.
Properties
items
:vec
Items that should be displayed in the combo boxtimeout
:duration
timeout of the command: Default: "200ms"onchange
:string
runs the code when a item was selected, replacing {} with the item as a string
expander
A widget that can expand and collapse, showing/hiding it's children. Should contain
Properties
name
:string
name of the expanderexpanded
:bool
sets if the tree is expanded
revealer
A widget that can reveal a child with an animation.
Properties
transition
:string
the name of the transition. Possible values: "slideright", "slideleft", "slideup", "slidedown", "crossfade", "none"reveal
:bool
sets if the child is revealed or notduration
:duration
the duration of the reveal transition. Default: "500ms"
a checkbox
A checkbox that can trigger events on checked / unchecked.
Properties
checked
:bool
whether the checkbox is toggled or not when createdtimeout
:duration
timeout of the command. Default: "200ms"onchecked
:string
action (command) to be executed when checked by the useronunchecked
:string
similar to onchecked but when the widget is unchecked
color-button
A button opening a color chooser window
Properties
use-alpha
:bool
bool to whether or not use alphaonchange
:string
runs the code when the color was selectedtimeout
:duration
timeout of the command. Default: "200ms"
color-chooser
A color chooser widget
Properties
use-alpha
:bool
bool to wether or not use alphaonchange
:string
runs the code when the color was selectedtimeout
:duration
timeout of the command. Default: "200ms"
scale
A slider.
Properties
flipped
:bool
flip the directionmarks
:string
draw marksdraw-value
:bool
draw the value of the propertyround-digits
:int
Sets the number of decimals to round the value to when it changesvalue
:float
the valuemin
:float
the minimum valuemax
:float
the maximum valuetimeout
:duration
timeout of the command. Default: "200ms"onchange
:string
command executed once the value is changes. The placeholder{}
, used in the command will be replaced by the new value.orientation
:string
orientation of the widget. Possible values: "vertical", "v", "horizontal", "h"
progress
A progress bar. HINT: for the width
property to work, you may need to set the min-width
of progressbar > trough
in your css.
Properties
flipped
:bool
flip the directionvalue
:float
value of the progress bar (between 0-100)orientation
:string
orientation of the progress bar. possible values: "vertical", "v", "horizontal", "h"
input
An input field. For this to be useful, set focusable="true"
on the window.
Properties
value
:string
the content of the text fieldonchange
:string
Command to run when the text changes. The placeholder{}
will be replaced by the valuetimeout
:duration
timeout of the command. Default: "200ms"onaccept
:string
Command to run when the user hits return in the input field. The placeholder{}
will be replaced by the valuepassword
:bool
if the input is obscured
button
A button containing any widget as it's child. Events are triggered on release.
Properties
timeout
:duration
timeout of the command. Default: "200ms"onclick
:string
command to run when the button is activated either by leftclicking or keyboardonmiddleclick
:string
command to run when the button is middleclickedonrightclick
:string
command to run when the button is rightclicked
image
A widget displaying an image
Properties
path
:string
path to the image fileimage-width
:int
width of the imageimage-height
:int
height of the imagepreserve-aspect-ratio
:bool
whether to keep the aspect ratio when resizing an image. Default: true, false doesn't work for all image typesfill-svg
:string
sets the color of svg imagesicon
:string
name of a theme iconicon-size
:string
size of the theme icon
box
the main layout container
Properties
spacing
:int
spacing between elementsorientation
:string
orientation of the box. possible values: "vertical", "v", "horizontal", "h"space-evenly
:bool
space the widgets evenly.
overlay
a widget that places its children on top of each other. The overlay widget takes the size of its first child.
Properties
tooltip
A widget that have a custom tooltip. The first child is the content of the tooltip, the second one is the content of the widget.
Properties
centerbox
a box that must contain exactly three children, which will be layed out at the start, center and end of the container.
Properties
orientation
:string
orientation of the centerbox. possible values: "vertical", "v", "horizontal", "h"
scroll
a container with a single child that can scroll.
Properties
hscroll
:bool
scroll horizontallyvscroll
:bool
scroll vertically
eventbox
a container which can receive events and must contain exactly one child. Supports :hover
and :active
css selectors.
Properties
timeout
:duration
timeout of the command. Default: "200ms"onscroll
:string
event to execute when the user scrolls with the mouse over the widget. The placeholder{}
used in the command will be replaced with eitherup
ordown
.onhover
:string
event to execute when the user hovers over the widgetonhoverlost
:string
event to execute when the user losts hovers over the widgetcursor
:string
Cursor to show while hovering (see gtk3-cursors for possible names)ondropped
:string
Command to execute when something is dropped on top of this element. The placeholder{}
used in the command will be replaced with the uri to the dropped thing.dragvalue
:string
URI that will be provided when dragging from this widgetdragtype
:string
Type of value that should be dragged from this widget. Possible values: "file", "text"onclick
:string
command to run when the widget is clickedonmiddleclick
:string
command to run when the widget is middleclickedonrightclick
:string
command to run when the widget is rightclicked
label
A text widget giving you more control over how the text is displayed
Properties
text
:string
the text to displaytruncate
:bool
whether to truncate text (or pango markup). Ifshow-truncated
isfalse
, or iflimit-width
has a value, this property has no effect and truncation is enabled.limit-width
:int
maximum count of characters to displaytruncate-left
:bool
whether to truncate on the left sideshow-truncated
:bool
show whether the text was truncated. Disabling it will also disable dynamic truncation (the labels won't be truncated more thanlimit-width
, even if there is not enough space for them), and will completly disable truncation on pango markup.unindent
:bool
whether to remove leading spacesmarkup
:string
Pango markup to displaywrap
:bool
Wrap the text. This mainly makes sense if you set the width of this widget.angle
:float
the angle of rotation for the label (between 0 - 360)gravity
:string
the gravity of the string (south, east, west, north, auto). Text will want to face the direction of gravity.xalign
:float
the alignment of the label text on the x axis (between 0 - 1, 0 -> left, 0.5 -> center, 1 -> right)yalign
:float
the alignment of the label text on the y axis (between 0 - 1, 0 -> bottom, 0.5 -> center, 1 -> top)justify
:string
the justification of the label text (left, right, center, fill)
literal
A widget that allows you to render arbitrary yuck.
Properties
content
:string
inline yuck that will be rendered as a widget.
calendar
A widget that displays a calendar
Properties
day
:float
the selected daymonth
:float
the selected monthyear
:float
the selected yearshow-details
:bool
show detailsshow-heading
:bool
show heading lineshow-day-names
:bool
show names of daysshow-week-numbers
:bool
show week numbersonclick
:string
command to run when the user selects a date. The{0}
placeholder will be replaced by the selected day,{1}
will be replaced by the month, and{2}
by the year.timeout
:duration
timeout of the command. Default: "200ms"
stack
A widget that displays one of its children at a time
Properties
selected
:int
index of child which should be showntransition
:string
the name of the transition. Possible values: "slideright", "slideleft", "slideup", "slidedown", "crossfade", "none"same-size
:bool
sets whether all children should be the same size
transform
A widget that applies transformations to its content. They are applied in the following order: rotate -> translate -> scale
Properties
rotate
:float
the percentage to rotatetransform-origin-x
:string
x coordinate of origin of transformation (px or %)transform-origin-y
:string
y coordinate of origin of transformation (px or %)translate-x
:string
the amount to translate in the x direction (px or %)translate-y
:string
the amount to translate in the y direction (px or %)scale-x
:string
the amount to scale in the x direction (px or %)scale-y
:string
the amount to scale in the y direction (px or %)
circular-progress
A widget that displays a circular progress bar
Properties
value
:float
the value, between 0 - 100start-at
:float
the percentage that the circle should start atthickness
:float
the thickness of the circleclockwise
:bool
wether the progress bar spins clockwise or counter clockwise
graph
A widget that displays a graph showing how a given value changes over time
Properties
value
:float
the value, between 0 - 100thickness
:float
the thickness of the linetime-range
:duration
the range of time to showmin
:float
the minimum value to show (defaults to 0 if value_max is provided)max
:float
the maximum value to showdynamic
:bool
whether the y range should dynamically change based on valueline-style
:string
changes the look of the edges in the graph. Values: "miter" (default), "round",flip-x
:bool
whether the x axis should go from high to lowflip-y
:bool
whether the y axis should go from high to lowvertical
:bool
if set to true, the x and y axes will be exchanged
systray
Tray for system notifier icons
Properties
spacing
:int
spacing between elementsorientation
:string
orientation of the box. possible values: "vertical", "v", "horizontal", "h"space-evenly
:bool
space the widgets evenly.icon-size
:int
size of icons in the trayprepend-new
:bool
prepend new icons.
Troubleshooting
Here you will find help if something doesn't work. If the issue isn't listed here, please open an issue on the GitHub repo.
Eww does not compile
- Make sure that you are compiling eww using a recent version of rust (run
rustup update
to be sure you have the latest version available) - Make sure you have all the necessary dependencies. If there are compile-errors, the compiler will tell you what you're missing.
Eww does not work on Wayland
- Make sure you compiled eww with the
--no-default-features --features=wayland
flags. - Make sure that you're not trying to use X11-specific features (these are (hopefully) explicitly specified as such in the documentation).
My configuration is not loaded correctly
- Make sure the
eww.yuck
andeww.(s)css
files are in the correct places. - Sometimes, eww might fail to load your configuration as a result of a configuration error. Make sure your configuration is valid.
Something isn't styled correctly!
Check the GTK-Debugger to get more insight into what styles GTK is applying to which elements.
General issues
You should try the following things before opening an issue or doing more specialized troubleshooting:
- Kill the eww daemon by running
eww kill
and re-open your window with the--debug
-flag to get additional log output. - Now you can take a look at the logs by running
eww logs
. - Use
eww state
to see the state of all variables. - Use
eww debug
to see the structure of your widget and other information. - Update to the latest eww version.
- Sometimes hot reloading doesn't work. In that case, you can make use of
eww reload
manually.
Remember, if your issue isn't listed here, open an issue on the GitHub repo.
Example Configurations
These configurations of eww are available in the examples/
directory of the repo.
An eww bar configuration:
A demo on how to declare and use data structures: