Skip to content

How to set up external bars

Bakkeby edited this page Dec 22, 2024 · 2 revisions

Some people may prefer to use an external bar instead of the built-in bar that comes with dusk.

This guide goes through the basic steps that you can take to make dusk use a standalone bar.

General idea

Add configuration that will allow dusk to replace the internal bar with the external bar.

Approach

Refer to the bars configuration item that controls what bars are present.

static const BarDef bars[] = {
	/* monitor idx  vert   x     y      w     h     name            ext class  ext inst  ext name */
	{  0,      0,   0,    "0%    0%     100% -1h ", "Primary top" },
	{  0,      1,   0,    "0%    100%   100% -1h ", "Primary bottom" },
	{  1,      0,   0,    "0%    0%     100% -1h ", "Secondary top" },
	{  1,      1,   0,    "0%    100%   100% -1h ", "Secondary bottom" },
	{  2,      0,   0,    "0%    0%     100% -1h ", "Tertiary top" },
	{  2,      1,   0,    "0%    100%   100% -1h ", "Tertiary bottom" },
};

If you have a single monitor then only the first two (monitor 0) settings will apply.

Note the optional ext class, ext instance and ext name settings on the right hand side. These are filters that can be used to match an external bar window in a similar way to how client rules work.

You can use xprop to get the class, instance and window title from the external bar window, e.g.

$ xprop | grep -E "WM_(CLASS|NAME)"
WM_CLASS(STRING) = "polybar", "Polybar"
WM_NAME(STRING) = "polybar-example_DP-1"

Then you can add those in the bars configuration above.

static const BarDef bars[] = {
	/* monitor idx  vert   x     y      w     h     name              ext class   ext inst  ext name  */
	{  0,      0,   0,    "0%    0%     100% -1h ", "Primary top",    "Polybar",  NULL,     "polybar-example_DP-1" },
	{  0,      1,   0,    "0%    100%   100% -1h ", "Primary bottom" },
	...
};

In the above example instance filter is left as NULL, which means that dusk will not try to match on the instance property.


Alternatively you can also enable Debug logging to see what is being checked when the bar window asks to be mapped.

matchextbar: checking new window polybar-example_DP-1 (62914562), class = 'Polybar', instance = 'polybar'
             against external bar 0 monitor 0 class = 'Polybar', instance = 'NULL', name = 'polybar-example_DP-1'
matchextbar: window 62914562 is a match for external bar 0 monitor 0

Note that if the bar window does not match (as will be the case the first time you start it) then the handling of the window will be subject to normal client rules.

If there is an exact match then the expectation is that the external bar should seamlessly replace the internal bar at the designated position.

The width and height of the bar is kept as-is (i.e. this is controlled by the external program) rather than the w and h settings in the bars configuration. The position of the bar is, however, taken by the x and y settings rather than what may be specified by the program.

All interaction between the external bar and the window manager take place via EWMH.

If the external bar is killed then dusk will seamlessly fall back to using the built-in bar.

Some things to consider:

  • you may want to disable the Systray functionality if the external bar handles that
  • you can have different bars on a per monitor basis by configuring and matching distinct names
  • not all WM features will fit well with an external bar, for example it may be complicated to find and unhide a hidden window, so it may be worth removing certain keybindings

Back to Guides.

Clone this wiki locally