This makes it possible to have the systray only visible on the primary screen,
which is the new default value. This also makes it possible to configure
directly on which screen the systray should be visible.
This breaks the API in the sense that people who use "the old method" to
configure the systray's screen possibly don't have a systray.
Fixes: https://github.com/awesomeWM/awesome/issues/724
Signed-off-by: Uli Schlachter <psychon@znc.in>
There's no point in having multiple instances of this, because there are no
per-instance settings and the systray can only be visible in a single place at a
time anyway.
Signed-off-by: Uli Schlachter <psychon@znc.in>
* Better widget names when using the declarative syntax
* Add ratio.get_ratio to avoid using the private API
* Also support `set_widget` when swapping widgets
Issues involve:
- :layout() had the wrong signature and expected a cr argument that was left
from when this was still the :draw() function.
- horizontal and vertical reflection were mixed up (I guess it has always been
this way?)
- The return value should be a table of widget placements. Instead it was just a
single widget placement.
This is broken since commit 85ab3f045b.
Fixes: https://github.com/awesomeWM/awesome/issues/718
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit makes these methods invoke the method on a widget in a protected
context. Thanks to this, e.g. the wibox and other widgets are protected from
errors in a child widget.
Additionally, fit_widget() now assumes 0 if a widget's :fit() method didn't
provide a number.
Signed-off-by: Uli Schlachter <psychon@znc.in>
I just spent too much time tracking down a bug that happened while drawing a
widget. This is the reason why we should apply sanity checks while widgets are
constructed, so that we get a useful backtrace.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This makes the code use the existing functions for setting widgets. That way,
all the sanity checks that the existing functions have are applied for this code
as well.
I just spent half an hour tracking down a bug where a boolean ended up as a
"widget" in a fixed layout. The symptom was that while drawing the widget, an
error happened. Via this change, the error would instead be flagged while
constructing the widget.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit documents that a textbox already accepts a screen object where a
screen index is expected. Also, this changes the widget API in that a widget's
context.screen is now a screen object instead of a screen index.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This layout allow each widgets to take 'r' percent of the total
space, where 'r' is configurable.
It re-implement the 'wfact' system used by `awful.layout.suit.tile`
This layout display the widgets on top of each other. It can also optionally
display only the first one.
The most common use case is to create a composited widget. Other use case
include the creation of a "paged" stack to only display the most
relevant widget without adding extra complexity to the parent layout.
This new syntax is inspired by the Awesome widget 3.2-3.4 API. It
allow cleaner widgets declaration. The produced code is usually much
shorted and easier to read than wibox.widget imperative syntax.
There is already a hack into `awful.widget.common`. This system aim
to make the hack obselete while preserving the useful part.
I think this is also necessary to properly support SVG (with DPI
and resize).
Finally, Qt handle this using the QBrush concept, where you can have
programmatic patterns. Cairo doesn't have this concept, so there is no
"clean" way to have programmatic brushes.
It's unused since commit 0aa4304bda. Before this was a stable sorting
algorithm since table.sort is allowed to be unstable. Apparently we don't need a
stable sorting algorithm anymore.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Until now, this layout was "append only". There was no official
APIs to remove, replace, insert and swap widgets. This is fine
for the usual wibox + sensors widget used by the majority of
users, but lack flexibility necessary to use the layout system
to place dynamic elements such as clients.
The methods introduced by this commit are also recursive. This
allow widgets to be decorated, wrapped and splitted without
having to add boilerplate code everywhere.
This remove duplicated code and will allow more "collection"
style layouts to be implemented without logic duplication.
This commit also do some small cleanup to remove duplicated
code now present in `awful.util`.
Fixes https://github.com/awesomeWM/awesome/issues/617
Instead of throwing a Lua error, the code now just prints an error message to
stderr on invalid markup. For callers which want to handle this case specially,
we add :set_markup_silently() which returns error messages.
Fixes: https://github.com/awesomeWM/awesome/issues/546
Signed-off-by: Uli Schlachter <psychon@znc.in>
Without this fix `wibox.widget.textbox` ignores current theme font
setting and resets it to the initial one.
It becomes handy when the initial theme is tweaked during runtime, ie.
in `rc.lua`. Other AwesomeWM components like `awful` (taglist,
tasklist, menu) are aware and do respect the actual theme settings.
Closes https://github.com/awesomeWM/awesome/pull/89.
This adds new functions to all widgets that allow to force a specific
width/height. These values override the result from :fit().
Signed-off-by: Uli Schlachter <psychon@znc.in>
When emitting layout_changed, the widget is relayouted. If this doesn't actually
change anything, nothing will be redrawn. Thus, this also emits redraw_needed to
force redraws.
This fixes a race condition with some weird tray icons. A new tray icon is
created and the systray is updated. Then this new icon is destroyed immediately
again and at the same time another icon is created. Then, the systray isn't
updated since the number of icons (=the layout) did not actually change.
However, it needs to be updated and so we ended up with broken/missing icons.
Fixes: https://github.com/awesomeWM/awesome/issues/487
Signed-off-by: Uli Schlachter <psychon@znc.in>
This allows scrolling a widget if there is too few space available. There are
several different modes available for how the scrolling "looks like".
Signed-off-by: Uli Schlachter <psychon@znc.in>
This adds :get_preferred_size() and :get_preferred_size_at_dpi() which return
the size (=width, height) that the textbox would need if unlimited space is
available.
This also adds :get_height_for_width() and :get_height_for_width_at_dpi() which
return the height that the textbox would need if the given width is available.
Signed-off-by: Uli Schlachter <psychon@znc.in>
If someone modifies a cairo surface and then sets the resulting object as the
image of an imagebox, the imagebox needs to redraw. Thus, since surfaces are
modifiable, we cannot assume that nothing changed when the same image is set
multiple times on an imagebox.
However, the dimensions of a surface cannot be changed and thus this does not
need to emit widget::layout_changed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit does two things: It gets rid of the reference to the layoutbox that
the default config created and it changes the widget dependency cache to not
keep widgets alive unnecessarily.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This function updates a hierarchy if the layout of some widgets changed. It does
nothing on the parts that did not change. This should be more efficient than
recomputing the whole hierarchy whenever something changes.
Once again, this has some positive results on the "benchmark test":
Before:
create wibox: 0.083016 sec/iter ( 13 iters, 1.161 sec for benchmark)
update textclock: 0.00391091 sec/iter (271 iters, 3.219 sec for benchmark)
relayout textclock: 0.00273234 sec/iter (397 iters, 1.087 sec for benchmark)
redraw textclock: 0.0010191 sec/iter (989 iters, 1.745 sec for benchmark)
After:
create wibox: 0.083146 sec/iter ( 13 iters, 1.163 sec for benchmark)
update textclock: 0.00170519 sec/iter (647 iters, 2.201 sec for benchmark)
relayout textclock: 0.000581637 sec/iter (1880 iters, 1.094 sec for benchmark)
redraw textclock: 0.0010167 sec/iter (997 iters, 1.773 sec for benchmark)
So again no difference for creating wiboxes (100.16% compared to before). This
time we also have no real difference for creating wiboxes (99.76%). Update (44%)
and relayout (21%) are improved a lot.
Closes https://github.com/awesomeWM/awesome/pull/463.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This makes the textbox' :draw() and :fit() callbacks use the DPI that is
specified in the given drawing context. With this, the textbox now scales
correctly if different screens have different DPI values.
Idea originally from Daniel.
Closes https://github.com/awesomeWM/awesome/pull/457.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This has some positive results on the "benchmark test". Each single number is
the best one out of three runs.
Before:
create wibox: 0.0826502 sec/iter ( 13 iters, 1.157 sec for benchmark)
update textclock: 0.0186952 sec/iter ( 57 iters, 2.473 sec for benchmark)
relayout textclock: 0.0158112 sec/iter ( 64 iters, 1.028 sec for benchmark)
redraw textclock: 0.0015197 sec/iter (662 iters, 1.861 sec for benchmark)
After:
create wibox: 0.0825672 sec/iter ( 13 iters, 1.154 sec for benchmark)
update textclock: 0.00378412 sec/iter (277 iters, 4.216 sec for benchmark)
relayout textclock: 0.00259056 sec/iter (420 iters, 1.09 sec for benchmark)
redraw textclock: 0.00105128 sec/iter (958 iters, 1.79 sec for benchmark)
We see no significant change in the creation of wiboxes (99.9% compared to
before). Update (20% of the previous run time), relayout (16%) and redraw (69%)
are all sped up by this change.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Before this, dependencies between widgets where implicitly discovered by
recursive calls to base.fit_widget() and base.layout_widget(). However, it is
too easy to get this wrong (just call one of these functions from outside of a
widget's :fit() / :layout() function) and the resulting mess would be hard to
debug.
Thus, this commit changes the API so that callers have to identify themselves
and we can explicitly record the dependency between the widgets involved.
This also fixes a bug where no dependencies were tracked for widgets after
:set_visible(false). Whoops...
Sorry for breaking the API for adding this.
Signed-off-by: Uli Schlachter <psychon@znc.in>
When a complete repaint is scheduled, also do a relayout, because this is also
the case that we go through when the underlying cairo surface is resized. For
example, resizing a client with a titlebar would trigger this.
Also, going through this code path is necessary since this is the only place
where the dirty area is updated so that it includes "everything". Before this
change, nothing was actually redrawn, because the dirty area was empty.
Fixes: https://github.com/awesomeWM/awesome/issues/449
Signed-off-by: Uli Schlachter <psychon@znc.in>
This accidentally called the draw callbacks with a nil argument instead of the
context. This was introduced in some badly done rebase, sorry! :-(
Signed-off-by: Uli Schlachter <psychon@znc.in>
The parent was needed for :get_matrix_to_device() which recursively walked
parents and multiplied together their transformation matrices. This is now
replaced by calculating all these matrices while constructing the hierarchy.
Signed-off-by: Uli Schlachter <psychon@znc.in>
There once was a function :get_root() on hierarchies, but that wasn't needed any
more and thus was removed. This commit also removes the internal code that was
used to record the root element of the hierarchy.
Signed-off-by: Uli Schlachter <psychon@znc.in>
These caches, well, cache the result of the :layout and :fit callbacks on
widgets.
Clearing caches is done by recording dependencies between a widget. When a call
to base.fit_widget() or base.layout_widget() recursively causes another call to
such a function, this means that the earlier widget depends on the later widget.
This dependency is recorded and when the later widget emits
widget::layout_changed, the caches of all the widgets involved are cleared.
Signed-off-by: Uli Schlachter <psychon@znc.in>
A widget hierarchy describes the position of widgets. The hierarchy is a
recursive tree of widget hierarchy instances. This functionality depends on a
:layout function that is not yet implemented on widgets, but will be added
later.
Signed-off-by: Uli Schlachter <psychon@znc.in>
After this change, fit_widget() enforces that a widget cannot ask for more space
than was offered to it. This also fixes a rounding issue in the flex layout
where its fit function would return too small numbers.
Thanks to this, lots of "XXX" comments in spec/ disappear.
Signed-off-by: Uli Schlachter <psychon@znc.in>
In expand nodes "none" and "outside", the variable size_remains describes how
much space is available for the first/third widget. Everything else is used by
the second widget. Thus, fitting the second widget to anything involving
size_remains is wrong. Instead, this commit uses the correct value.
This also fixes a messed up argument order for horizontal align layouts.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This table contains the drawable, wibox and titlebar that we are drawing on, but
also includes the screen and the DPI of that screen. This allows widgets to
depend on the DPI in their rendering.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Having two modules named "base" is confusing and "wibox.layout" doesn't contain
much useful stuff. This is a first step for removing wibox.layout by moving a
function which should only ever be used internally in awesome.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This way "that other widget" doesn't prevent the current widget from being
garbage collected.
Please note that this in all of these cases the widget under consideration does
have a strong reference to the callback function. This means that the callback
cannot be garbage collected until "this widget" itself is collected. Thanks to
this, this change is safe.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This made it easier to figure out where a file causing an error was
coming from, but I could imagine that this could become too noisy, and
that there is/should probably be a more streamlined way to enable more
verbose logging / error output.
The old code transformed the top-left and bottom-right corner of the rectangle
to device space and calculated a rectangle based on these two points. However,
if you rotate a rectangle by 45°, these two points will be directly above each
other and thus the old code would calculate a width of 0.
Fix this by transforming all four corners of the rectangle into device space and
calculating a rectangle based on this.
Signed-off-by: Uli Schlachter <psychon@znc.in>
When an imagebox was drawn with width or height zero, it tried to calculate the
needed scale factor for making the image fit. Sadly, this would be a division by
zero aka infinite in this case.
Fix this by just not drawing anything if there is no space available.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Previously, odd things could happen if a widget was getting fitted into a
negative width or, even worse, width being NaN (not a number)!
This can e.g. happen due to a margin layout which doesn't get enough space to
even draw the margin that it is supposed to add.
Fix this by enforcing a minimum value of 0 for the width and height that a
widget gets fitted into.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Given an imagebox i with i.resize_forbidden = false and a valid image set, the
call t:fit(0, 0) would return two times "not a number".
This is because the code first does some calculations to get the input image
into the available space and then tried to do some calculations needed for
scaling images up.
The first calculation already gave us h == 0 == w, the second calculation would
then calculate 0/0. This results in NaNs.
This was only noticed because NaN is not a valid table index in lua.
Fix this by returning 0,0 if we have an image of width or height 0 after the
first calculation. Since 0x0 images are valid in cairo, this also fixes the same
bug with such images.
Signed-off-by: Uli Schlachter <psychon@znc.in>
If a drawable has an opaque background, we don't need pseudo transparency and
thus its content don't change when it is moved. However, when we need pseudo
transparency, then we have to redraw the drawable to apply the new background.
Previously we just always did the redraw. This commit adds a helper function
gears.color.create_opaque_pattern() that analyzes a cairo pattern for
transparency. We use this new function to only redraw-on-move when there is
actual pseudo transparency in effect. Otherwise, this redraw can be skipped.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Added set_expand function with options of "none" "outside" or "inside" modes.
The "inside" mode is the default and will result in the original behavior. The
main benefit is being able to actually center a widget in the available space
with options of how to draw the outside widgets (expand to take the space,
or not.) Further functionality can be had by ommiting one of the outside
widgets. Set default layout mode in the constructor.
Signed-off-by: Uli Schlachter <psychon@znc.in>