sfwbar
sfwbar copied to clipboard
Is there a way to make a "Show Desktop" button?
I want a button on my sfwbar that:
- Clicking once minimizes all windows
- Clicking another time restores all minimized windows
Windows has this at the bottom right corner. Wanted to mimic the same thing.
All I was able to make is a button that minimizes the current focused window and restores with another click:
function("ShowDesktop") {
[!Minimized] Minimize
[Minimized] UnMinimize
}
I don't think this is achievable with the existing functionality, but shouldn't be difficult to implement. The question is what from should implementation take. I think the options are:
- Implement is a new action - I dislike this approach because it implements one bit of functionality without making actions more flexible.
- Implement ForAllWindows option to a Function action. This will allow running the above function on all windows, but since the function flips the minimized state on the window, it will unminimize any already minimized windows, so we would also need to implement user definable state flag for windows.
- Implement ForAllChildren option to a Function action (to run action on all children of a widget). We can then run the function on all children of a taskbar. This will let us use the widgets user state flag to save the state and restore the windows accordingly.
I'm currently leaning towards option 3. The pros of this approach are leveraging existing user state infrastructure and taskbar output filtering options. The downside is that minimize desktop feature would only work if a taskbar is present (although this could be worked around by adding a taskbar and making it hidden).
I just started using sfwbar, so have no understanding what might be best. Looking forward to the feature.
I got the basic functionality working on my local machine, but realised that we'll also need an ability to filter by workspace, since we only want to minimise / restore windows on the current workspace.
On Tue, 20 Sept 2022, 19:29 hellium6, @.***> wrote:
I just started using sfwbar, so have no understanding what might be best. Looking forward to the feature.
— Reply to this email directly, view it on GitHub https://github.com/LBCrion/sfwbar/issues/49#issuecomment-1252752049, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASHPFFD7OCBXYD6JPAITNW3V7H67HANCNFSM6AAAAAAQQIW4IA . You are receiving this because you commented.Message ID: @.***>
This should now be possible in the latest git version. My config snippet is as following:
function("ShowdesktopMinimize") {
[!Minimized] Minimize
[!Minimized] UserState "on"
[Minimized] UserState "off"
}
function("ShowDesktopRestore") {
[UserState] UnMinimize
}
function("ShowDesktop") {
[!UserState | Children ] Function "ShowDesktopMinimize"
[UserState | Children ] Function "ShowDesktopRestore"
[!UserState] UserState "on"
[UserState] UserState "off"
}
layout "sfwbar" {
taskbar "target" {
rows = 2
css = "* { -GtkWidget-hexpand: true; }" # stretch horizontally
action = Function "FocusOrMinimize"
icons = true
labels = true
filter_output = true
sort = false
action[3] = Menu "winops"
}
button {
action[0] = UserState "off"
action = Function "target", "ShowDesktop"
value = "file-open"
}
...
This config uses the show desktop button's UserState to toggle between Show/Restore and uses taskbar's buttons UserState to keep track on which windows were already minimized and should not be restored.
One issue I found so far is that windows are not restored in the order they were in. I.e. a window that was on top before showing the desktop, may end up covered by other windows. I'm not sure this is something that can be easily resolved, as the is no way to query z-order of windows vis foreign toplevel protocol that I'm aware of.
no way to query z-order of windows via foreign toplevel protocol
You could maybe have a stack of toplevels and on each focus event remove the toplevel from the stack and insert it at the end again. Then when (un)minimizing you should have roughly the same z-order as the compositor. This may obviously not be perfect in all cases but could be something like a "usually working" solution.
Yes, that would probably the best we can achieve here, although I wonder if the list of events placing a window on top may be compositor dependent. So far I think the events that would place the window on top of the stack are: activate, unminimize, maximize, unmaximize and move to workspace. Of course workspaces pose a particular problem, since at least on sway unminimizing a window will activate a workspace to which the window is restored to. We may need to keep track of the current workspace and make sure we re- activate it after restoring the windows.
On Wed, 21 Sept 2022, 20:48 Consolatis, @.***> wrote:
no way to query z-order of windows vis foreign toplevel protocol that I'm aware of.
You could maybe have a stack of toplevels and on each focus event remove the toplevel from the stack and insert it at the end again. Then when minimizing you should roughly have the same z-order as the compositor. This may obviously be pretty hard to match in all cases though but could be something like a "usually working" "solution".
— Reply to this email directly, view it on GitHub https://github.com/LBCrion/sfwbar/issues/49#issuecomment-1254154296, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASHPFFHSKSRJLC623V6ZRSLV7NRBBANCNFSM6AAAAAAQQIW4IA . You are receiving this because you commented.Message ID: @.***>
I went down the path of least resistance for now. I added a second user state and save focused window into it. This way when restoring. The stack may be modified, but the active window will be on top.
function("ShowDesktopSave") {
[Focused] UserState "2:on"
[!Focused] UserState "2:off"
}
function("ShowdesktopMinimize") {
[!Minimized] UserState "on"
[Minimized] UserState "off"
[!Minimized] Minimize
}
function("ShowDesktopRestore") {
[UserState] UnMinimize
}
function("ShowDesktopRestoreFocus") {
[UserState2] Focus
}
function("ShowDesktop") {
[!UserState | Children ] Function "ShowDesktopSave"
[!UserState | Children ] Function "ShowDesktopMinimize"
[UserState | Children ] Function "ShowDesktopRestore"
[UserState | Children ] Function "ShowDesktopRestoreFocus"
[!UserState] UserState "on"
[UserState] UserState "off"
}
Sorry for late. I was surprised to see that there is no sfwbar-git AUR package. I had to make one myself. Although disclaimer, I'm not experienced with AUR packaging. I'm not sure if I'll be able to submit/update it as necessary so anybody interested, feel free to submit it to AUR.
I installed the latest git version and added the latest code in sfwbar.config. To test:
- I opened 2 windows
- When I click show desktop button, it just minimizes the focused window, not the other one
- When I click again nothing happens
- When I click it again, the focused window minimizes
Maybe I missed something. My config code:
function("ShowDesktopSave") {
[Focused] UserState "2:on"
[!Focused] UserState "2:off"
}
function("ShowdesktopMinimize") {
[!Minimized] UserState "on"
[Minimized] UserState "off"
[!Minimized] Minimize
}
function("ShowDesktopRestore") {
[UserState] UnMinimize
}
function("ShowDesktopRestoreFocus") {
[UserState2] Focus
}
function("ShowDesktop") {
[!UserState | Children ] Function "ShowDesktopSave"
[!UserState | Children ] Function "ShowDesktopMinimize"
[UserState | Children ] Function "ShowDesktopRestore"
[UserState | Children ] Function "ShowDesktopRestoreFocus"
[!UserState] UserState "on"
[UserState] UserState "off"
}
layout {
...
grid {
...
taskbar {
rows = 1
css = "* { -GtkWidget-hexpand: true; }" # stretch horizontally
#action = Function "FocusOrMinimize"
icons = true
labels = true
filter_output = true
action[3] = Menu "winops"
}
...
button {
style = "icon_button"
value = "desktop"
action = Function "ShowDesktop"
action[0] = UserState "off"
#action = Function "target", "ShowDesktop"
tooltip = "Show Desktop"
css = "* { min-height: 0.60cm; min-width: 0.60cm; }" # set icon size
}
} # end of grid#main
}
Try adding "target" between taskbar and { (I.e. taskbar "target" { ). The button calls the ShowDesktop function on children of the taskbar, so you need to be able to address the taskbar.
On Mon, 26 Sept 2022, 23:46 hellium6, @.***> wrote:
Sorry for late. I was surprised to see that there is no sfwbar-git AUR package. I had to make one myself https://gist.github.com/hellium6/3debde05e046842d3417ca8bdb02a983. Although disclaimer, I'm not experienced with AUR packaging. I'm not sure if I'll be able to submit/update it as necessary so anybody interested, feel free to submit it to AUR.
I installed the latest git version and added the latest code https://github.com/LBCrion/sfwbar/issues/49#issuecomment-1255875625 in sfwbar.config. To test:
- I opened 2 windows
- When I click show desktop button, it just minimizes the focused window, not the other one
- When I click again nothing happens
- When I click it again, the focused window minimizes
Maybe I missed something. My config code:
function("ShowDesktopSave") { [Focused] UserState "2:on" [!Focused] UserState "2:off" }
function("ShowdesktopMinimize") { [!Minimized] UserState "on" [Minimized] UserState "off" [!Minimized] Minimize }
function("ShowDesktopRestore") { [UserState] UnMinimize }
function("ShowDesktopRestoreFocus") { [UserState2] Focus }
function("ShowDesktop") { [!UserState | Children ] Function "ShowDesktopSave" [!UserState | Children ] Function "ShowDesktopMinimize" [UserState | Children ] Function "ShowDesktopRestore" [UserState | Children ] Function "ShowDesktopRestoreFocus" [!UserState] UserState "on" [UserState] UserState "off" }
layout { ... grid { ... taskbar { rows = 1 css = "* { -GtkWidget-hexpand: true; }" # stretch horizontally #action = Function "FocusOrMinimize" icons = true labels = true filter_output = true action[3] = Menu "winops" } ... button { style = "icon_button" value = "desktop" action = Function "ShowDesktop" action[0] = UserState "off" #action = Function "target", "ShowDesktop" tooltip = "Show Desktop" css = "* { min-height: 0.60cm; min-width: 0.60cm; }" # set icon size } } # end of grid#main }
— Reply to this email directly, view it on GitHub https://github.com/LBCrion/sfwbar/issues/49#issuecomment-1258734420, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASHPFFF4NK67FBCXNTQSIMTWAIRTPANCNFSM6AAAAAAQQIW4IA . You are receiving this because you commented.Message ID: @.***>
Thanks. It works now. Thanks for implementing this in a short time.
The changes I made:
taskbar "target" {
...
button {
...
#action = Function "ShowDesktop"
action[0] = UserState "off"
action = Function "target", "ShowDesktop"
btw, what does the line action[0] = UserState "off"
do? I tried without it and it seems to be working fine.
I wanted to highlight another issue-
- If I click the button and it minimizes all windows. Then I open a new window.
- Clicking the button minimizes the new window, but restores windows that were minimized earlier.
- Clicking another time minimizes all.
- Clicking another time restores the other windows but not the new window.
I think the behavior should be-
- if even one window is restored, it should minimize it, keeping other minimized windows untouched - idea being to make sure all windows are minimized first
- clicking another time should restore all of them, even the new window
action[0] = UserState "off"
is probably unnecessary, it sets the initial value of UserState, but it's a precaution, since this should be initialzed to off anyway.
What compositor are you using? I don't see the behavior you describe on my setup (using sway or labwc)
I'm using labwc 0.5.3-1 from AUR.
I wanted to highlight another issue-
* If I click the button and it minimizes all windows. Then I open a new window. * Clicking the button minimizes the new window, but restores windows that were minimized earlier. * Clicking another time minimizes all. * Clicking another time restores the other windows but not the new window.
It's really odd that the new window is minimised. The ShowDesktop button toggles between two states: one where it minimizes windows and one where it unminimizes them. When you click it the first time it minimize windows and goes into unminimize mode. When you open a new window, it's still in the unminimize mode. So when you click it again, it shouldn't minimize a new window. Would you mind posting your full config, so I can check if I'm missing anything?
I think the behavior should be-
* if even one window is restored, it should minimize it, keeping other minimized windows untouched - idea being to make sure all windows are minimized first * clicking another time should restore all of them, even the new window
This would be quite fiddly to do. As I mentioned above the ShowDesktop button toggles between two states. To implement what you describe we need an additional states of additional minimisation. We could in theory run a function before unminimizing to check if any windows are still showing and go into additional minimization routine in this case. It would add more functions to the above, and will be a bit messy, but can be done. I'd like to figure out the first issue before trying to do this though.
I'm using labwc 0.5.3-1 from AUR.
It is also possible that labwc 0.5.3 is doing something wrong in regard to foreign toplevel states, the current master branch is basically a complete rewrite. @hellium6 does labwc-git from AUR show the same issue?
@LBCrion
Would you mind posting your full config, so I can check if I'm missing anything?
Sure, no problem.
I tried to copy from /usr/share/sfwbar/sfwbar.config
to ~/.config/sfwbar/sfwbar.config
and put the above code on this fresh copy so that it is easier to test and reproduce and my changes doesn't affect the results. Here's the diff and here's the whole config.
It happens with this config too.
@Consolatis
does labwc-git from AUR show the same issue?
It cannot be installed. labwc-git needs wlroots>=0.16
. I tried to install wlroots-git but it fails with some build error /usr/include/wlr/types/wlr_screencopy_v1.h:48:29: error: field ‘buffer_cap’ has incomplete type
.
I even tried to download PKGBUILD and manually build so that it gets the latest git commit, but same result. The AUR page for labwc-git has a comment by the maintainer that says:
This is broken until wlroots 0.15.0 hits the repos. See https://aur.archlinux.org/packages/labwc-git/#comment-844664 for some more information. If you don't need wlroots-git for anything else, you could change the PKGBUILD to build from tag 0.15.x
I have no idea how to fix this.
The comment for the package is unrelated. It was an issue with wlroots upstream / wlroots-git from AUR, but that should be fixed now.
@helium6, this is very strange, I just built labwc 5.3 locally and tried running it with the config your posted. I still get the expected behaviour:
- I open 2 windows.
- I press the show desktop button and they are minimized
- I open a third window
- I press the show desktop button. Two minimized windows are unminimized and the new window is still open
- I press the show desktop button and all 3 windows are minimized
- I press the show desktop button and all 3 windows are unminimized.
Just to confirm, are you using the latest git version of sfwbar?
I press the show desktop button. Two minimized windows are unminimized and the new window is still open
I just checked and I get the same behavior here. Which is different from what I said:
Clicking the button minimizes the new window, ...
I think the new window got behind other windows and that made me think that it got minimized. Oops, that's my mistake. Sorry! I should've checked with resized windows side by side to test this better.
Please ignore what I said. If it can minimize all unminimized windows on click first, I think that would be good enough for me.
Just in case this is still useful:
pacman -Qs sfwbar
local/sfwbar-git r660.0590a4f-1
Sway Floating Window taskBar (git version)
Phew. I thought I was going mad here :)
Try this with the latest git version. I think it should get the behaviour you want in case additional windows are open while desktop is showing.
scanner {
# Extract memory usage information
file("/proc/meminfo") {
MemTotal = RegEx("^MemTotal:[\t ]*([0-9]+)[\t ]")
MemFree = RegEx("^MemFree:[\t ]*([0-9]+)[\t ]")
MemCache = RegEx( "^Cached:[\t ]*([0-9]+)[\t ]")
MemBuff = Regex("^Buffers:[\t ]*([0-9]+)[\t ]")
}
# Add up total and used swap capacity across all partitions
file("/proc/swaps") {
SwapTotal = RegEx("[\t ]([0-9]+)",Sum)
SwapUsed = RegEx("[\t ][0-9]+[\t ]([0-9]+)",Sum)
}
# Add up CPU utilization stats across all CPUs
file("/proc/stat") {
CpuUser = RegEx("^cpu [\t ]*([0-9]+)",Sum)
CpuNice = RegEx("^cpu [\t ]*[0-9]+ ([0-9]+)",Sum)
CpuSystem = RegEx("^cpu [\t ]*[0-9]+ [0-9]+ ([0-9]+)",Sum)
CpuIdle = RegEx("^cpu [\t ]*[0-9]+ [0-9]+ [0-9]+ ([0-9]+)",Sum)
}
# Get total and remaining battery charge
file("/sys/class/power_supply/BAT0/charge_full") {
BatteryTotal = Grab(Sum)
}
file("/sys/class/power_supply/BAT0/charge_now") {
BatteryLeft = Grab(Sum)
}
file("/sys/class/power_supply/AC/online") {
ACOnline = Grab(Sum)
}
}
# Window Placer
placer {
xorigin = 5 # place the first window at X% from the left
yorigin = 5 # place the first window at X% from the top
xstep = 5 # step by X% of desktop horizontally
ystep = 5 # step by X% of desktop vertically
children = true
}
# Task Switcher
switcher {
interval = 700
icons = true
labels = false
cols = 5
}
function("SfwbarInit") {
SetBarId "bar-0"
# SetLayer "bottom"
# SetMonitor "eDP-1"
# SetBarSize "800"
}
function("ToggleMinimize") {
[!Minimized] Minimize
[Minimized] UnMinimize
}
function("ToggleMaximize") {
[!Maximized] Maximize
[Maximized] UnMaximize
}
menu("winops") {
item("focus", Focus );
item("close", Close );
item("(un)minimize", Function "ToggleMinimize" );
item("(un)maximize", Function "ToggleMaximize" );
}
# Added code for Show Desktop button:
function("ShowDesktopSave") {
[Focused] UserState "2:on"
[!Focused] UserState "2:off"
}
function("ShowdesktopMinimize") {
[!Minimized] UserState "on"
[Minimized] UserState "off"
[!Minimized] Minimize
}
function("ShowDesktopRestore") {
[UserState] UnMinimize
}
function("ShowDesktopRestoreFocus") {
[UserState2] Focus
}
function("ShowDesktopCheckWindow") {
[!Minimized] UserState "target","2:on"
}
function("ShowDesktopCheckWindows") {
UserState "target","2:off"
[Children] Function "ShowDesktopCheckWindow"
Function "target","ShowDesktopUnminimized"
}
function("ShowDesktopReminimize")
{
[!Minimized] UserState "on"
[!Minimized] Minimize
}
function("ShowDesktopUnminimized") {
[UserState2 | Children] Function "ShowDesktopReminimize"
[!UserState2 | Children] Function "ShowDesktopRestore"
[!UserState2 | Children] Function "ShowDesktopRestoreFocus"
[!UserState2] UserState "off"
[UserState2] UserState "on"
}
function("ShowDesktop") {
[!UserState | Children ] Function "ShowDesktopSave"
[!UserState | Children ] Function "ShowDesktopMinimize"
[UserState] Function "ShowDesktopCheckWindows"
# [UserState | Children ] Function "ShowDesktopRestore"
# [UserState | Children ] Function "ShowDesktopRestoreFocus"
[!UserState] UserState "on"
}
# Panel layout
layout {
taskbar "target" {
rows = 2
css = "* { -GtkWidget-hexpand: true; }" # stretch horizontally
icons = true
labels = true
filter_output = true
action[3] = Menu "winops"
}
# label { css = "* { -GtkWidget-hexpand: true; }" }
# add a pager
pager {
style = "pager"
rows = 2
preview = true
numeric = true
pins = "1","2","3","4"
}
# add a launcher
button {
value = "firefox"
action = "firefox" # launch firefox on click
css = "* { min-height: 1.25cm; min-width: 1.25cm; }" # set icon size
}
button {
value = "Alacritty"
action = "alacritty"
css = "* { min-width: 1.25cm; min-height: 1.25cm; }";
}
include("idle.widget")
grid {
scale {
interval = 1000
css = "progressbar progress { background-color: #0000ff;}"
action[4] = "alacritty -e top"
value = (CpuUser-CpuUser.pval)/(CpuUser+CpuNice+CpuSystem+CpuIdle
-CpuUser.pval-CpuNice.pval-CpuSystem.pval-CpuIdle.pval)
tooltip = Str((CpuUser-CpuUser.pval)/(CpuUser+CpuNice+CpuSystem+CpuIdle
-CpuUser.pval-CpuNice.pval-CpuSystem.pval-CpuIdle.pval)*100,0)+'%'
}
scale {
interval = 1000
css = "progressbar progress { background-color: #00ff00;}"
value= (MemTotal-MemFree-MemCache-MemBuff)/MemTotal
}
scale {
interval = 1000
style = ACOnline
css = "progressbar#1 progress { background-color: #ff0000;} \
progressbar#0 progress { background-color: #ffff00;}"
value = BatteryLeft/BatteryTotal
}
}
include("mpd.widget")
tray {
rows = 2
}
grid {
style = "frame"
css = "* { -GtkWidget-direction: right; }"
label { loc(1,1) }
include("cpu-temp.widget")
label { loc(1,2) }
include("lan-bps.widget")
label { loc(1,3) }
include("mb-temp.widget")
label { loc(1,4) }
include("fan-rpm.widget")
}
include("weather.widget")
include("clock.widget")
# Add the Show Desktop button
button {
value = "desktop"
action = Function "target", "ShowDesktop"
css = "* { min-height: 1.25cm; min-width: 1.25cm; }" # set icon size
}
}
#CSS
window {
-GtkWidget-direction: bottom;
}
#hidden {
-GtkWidget-visible: false;
}
button#taskbar_normal grid {
-GtkWidget-hexpand: false;
padding-right: 0px;
margin-right: 0px;
}
button#taskbar_normal image, button#taskbar_active image, button#taskbar_normal:hover image {
min-width: 0.4cm;
min-height: 0.4cm;
}
button#taskbar_normal label, button#taskbar_active label, button#taskbar_normal:hover label {
-GtkWidget-vexpand: true;
-GtkWidget-hexpand: false;
padding-left: 0.75mm;
padding-top: 0px;
padding-bottom: 0px;
font: 0.3cm Sans;
}
button#taskbar_normal , button#taskbar_active , button#taskbar_normal:hover {
padding-left: 0.75mm;
padding-top: 0.5mm;
padding-bottom: 0.5mm;
background-image: none;
border-radius: 0;
border-image: none;
-GtkWidget-hexpand: false;
}
button#taskbar_active {
background-color: #bbddff;
}
button#taskbar_normal:hover {
background-color: #cccccc;
}
button#pager_normal , button#pager_visible , button#pager_focused {
padding-left: 1.25mm;
padding-right: 1.25mm;
padding-top: 0.5mm;
padding-bottom: 0.5mm;
background-image: none;
border-radius: 0;
border-image: none;
font: 0.3cm Sans;
}
button#pager_focused {
background-color: #bbddff;
}
button#pager_preview {
background-image: none;
border-radius: 0;
border-image: none;
border-color: #000000;
border-width: 0.25mm;
color: #777777;
min-width: 5cm;
min-height: 2.8125cm;
}
grid#pager {
outline-color: #000000;
outline-style: dashed;
outline-width: 0.25mm;
}
grid#switcher_active image,
grid#switcher_active {
min-width: 1.25cm;
min-height: 1.25cm;
border-image: none;
padding: 1.25mm;
background-color: #bbddff;
border-radius: 1.25mm;
-GtkWidget-hexpand: true;
}
grid#switcher_normal image,
grid#switcher_normal {
min-width: 1.25cm;
min-height: 1.25cm;
border-image: none;
padding: 1.25mm;
-GtkWidget-direction: right;
-GtkWidget-hexpand: true;
}
window#switcher {
border-style: solid;
border-width: 0.25mm;
border-color: #000000;
border-radius: 1.25mm;
padding: 1.25mm;
-GtkWidget-hexpand: true;
}
grid#switcher {
border-radius: 1.25mm;
padding: 1.25mm;
-GtkWidget-hexpand: true;
}
button#tray_active,
button#tray_passive,
button#tray_attention {
background-image: none;
border: 0px;
padding: 0px;
margin: 0px;
border-image: none;
border-radius: 0px;
outline-style: none;
box-shadow: none;
}
button#tray_active image,
button#tray_passive image,
button#tray_attention image {
-GtkWidget-hexpand: true;
-GtkWidget-vexpand: true;
padding: 1mm;
}
progressbar {
padding-left: 0.25mm;
padding-right: 0.25mm;
-GtkWidget-vexpand: true;
-GtkWidget-direction: top;
}
progress, trough {
border-radius: 0;
border-color: #9c9c9c;
}
progress {
border-style: outset;
min-width: 2mm;
}
trough {
background-color: #a1a1a1;
border-style: inset;
min-height: 2.5mm;
min-width: 2.5mm;
}
grid#frame {
-GtkWidget-direction: bottom;
min-width: 2cm;
border-color: #9c9c9c;
border-style: groove;
border-width: 0.5mm;
padding-top: 0.25mm;
}
grid#layout {
padding: 0.25mm;
-GtkWidget-direction: right;
}
label#value {
-GtkWidget-hexpand: true;
-GtkWidget-align: 1;
padding-right: 2mm;
padding-left: 2mm;
}
image#value_icon {
min-width: 0.3cm;
min-height: 0.3cm;
}
label#mpd {
padding-top: 1mm;
padding-bottom: 1mm;
padding-left: 2mm;
padding-right: 2mm;
}
image#mpd {
min-width: 0.4cm;
min-height: 0.4cm;
padding-left: 0.5mm;
padding-right: 0.5mm;
}
button#idle_inhibit {
-GtkWidget-vexpand: true;
}
label {
font: 0.27cm Sans;
}
label#awesome {
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
Thank you so much! This time it minimized the newest window. I tried with all resized windows to test this time so that I don't get confused.
I used the latest commit version:
$ pacman -Qs sfwbar
local/sfwbar-git r671.0cba480-1
Sway Floating Window taskBar (git version)
Just one small note. The new window, when unminimized later with the press of the button, goes behind other windows. If I'm not being a trouble, can this be fixed? If it's too complicated, I can live with that for now.
This was a question I ran into when coding this up. Which window should have focus on restore: the original focused window or the newly opened focused window. I do far opted do the former (mainly because its less work), but can change to later. Will try to update config for it when I have a moment
This version should restore focus to the window that was last focused:
scanner {
# Extract memory usage information
file("/proc/meminfo") {
MemTotal = RegEx("^MemTotal:[\t ]*([0-9]+)[\t ]")
MemFree = RegEx("^MemFree:[\t ]*([0-9]+)[\t ]")
MemCache = RegEx( "^Cached:[\t ]*([0-9]+)[\t ]")
MemBuff = Regex("^Buffers:[\t ]*([0-9]+)[\t ]")
}
# Add up total and used swap capacity across all partitions
file("/proc/swaps") {
SwapTotal = RegEx("[\t ]([0-9]+)",Sum)
SwapUsed = RegEx("[\t ][0-9]+[\t ]([0-9]+)",Sum)
}
# Add up CPU utilization stats across all CPUs
file("/proc/stat") {
CpuUser = RegEx("^cpu [\t ]*([0-9]+)",Sum)
CpuNice = RegEx("^cpu [\t ]*[0-9]+ ([0-9]+)",Sum)
CpuSystem = RegEx("^cpu [\t ]*[0-9]+ [0-9]+ ([0-9]+)",Sum)
CpuIdle = RegEx("^cpu [\t ]*[0-9]+ [0-9]+ [0-9]+ ([0-9]+)",Sum)
}
# Get total and remaining battery charge
file("/sys/class/power_supply/BAT0/charge_full") {
BatteryTotal = Grab(Sum)
}
file("/sys/class/power_supply/BAT0/charge_now") {
BatteryLeft = Grab(Sum)
}
file("/sys/class/power_supply/AC/online") {
ACOnline = Grab(Sum)
}
}
# Window Placer
placer {
xorigin = 5 # place the first window at X% from the left
yorigin = 5 # place the first window at X% from the top
xstep = 5 # step by X% of desktop horizontally
ystep = 5 # step by X% of desktop vertically
children = true
}
# Task Switcher
switcher {
interval = 700
icons = true
labels = false
cols = 5
}
function("SfwbarInit") {
SetBarId "bar-0"
# SetLayer "bottom"
# SetMonitor "eDP-1"
# SetBarSize "800"
}
function("ToggleMinimize") {
[!Minimized] Minimize
[Minimized] UnMinimize
}
function("ToggleMaximize") {
[!Maximized] Maximize
[Maximized] UnMaximize
}
menu("winops") {
item("focus", Focus );
item("close", Close );
item("(un)minimize", Function "ToggleMinimize" );
item("(un)maximize", Function "ToggleMaximize" );
}
# Added code for Show Desktop button:
function("ShowDesktopSave") {
[Focused] UserState "2:on"
[!Focused] UserState "2:off"
}
function("ShowdesktopMinimize") {
[!Minimized] UserState "on"
[Minimized] UserState "off"
[!Minimized] Minimize
}
function("ShowDesktopRestore") {
[UserState] UnMinimize
}
function("ShowDesktopRestoreFocus") {
[UserState2] Focus
}
function("ShowDesktopCheckWindow") {
[!Minimized] UserState "target","2:on"
}
function("ShowDesktopCheckWindows") {
UserState "target","2:off"
[Children] Function "ShowDesktopCheckWindow"
Function "target","ShowDesktopUnminimized"
}
function("ShowDesktopReminimize")
{
[!Minimized] UserState "on"
[!Minimized] Minimize
}
function("ShowDesktopUnminimized") {
[UserState2 | Children] Function "ShowDesktopSave"
[UserState2 | Children] Function "ShowDesktopReminimize"
[!UserState2 | Children] Function "ShowDesktopRestore"
[!UserState2 | Children] Function "ShowDesktopRestoreFocus"
[!UserState2] UserState "off"
[UserState2] UserState "on"
}
function("ShowDesktop") {
[!UserState | Children ] Function "ShowDesktopSave"
[!UserState | Children ] Function "ShowDesktopMinimize"
[UserState] Function "ShowDesktopCheckWindows"
# [UserState | Children ] Function "ShowDesktopRestore"
# [UserState | Children ] Function "ShowDesktopRestoreFocus"
[!UserState] UserState "on"
}
# Panel layout
layout {
taskbar "target" {
rows = 2
css = "* { -GtkWidget-hexpand: true; }" # stretch horizontally
icons = true
labels = true
filter_output = true
action[3] = Menu "winops"
}
# label { css = "* { -GtkWidget-hexpand: true; }" }
# add a pager
pager {
style = "pager"
rows = 2
preview = true
numeric = true
pins = "1","2","3","4"
}
# add a launcher
button {
value = "firefox"
action = "firefox" # launch firefox on click
css = "* { min-height: 1.25cm; min-width: 1.25cm; }" # set icon size
}
button {
value = "Alacritty"
action = "alacritty"
css = "* { min-width: 1.25cm; min-height: 1.25cm; }";
}
include("idle.widget")
grid {
scale {
interval = 1000
css = "progressbar progress { background-color: #0000ff;}"
action[4] = "alacritty -e top"
value = (CpuUser-CpuUser.pval)/(CpuUser+CpuNice+CpuSystem+CpuIdle
-CpuUser.pval-CpuNice.pval-CpuSystem.pval-CpuIdle.pval)
tooltip = Str((CpuUser-CpuUser.pval)/(CpuUser+CpuNice+CpuSystem+CpuIdle
-CpuUser.pval-CpuNice.pval-CpuSystem.pval-CpuIdle.pval)*100,0)+'%'
}
scale {
interval = 1000
css = "progressbar progress { background-color: #00ff00;}"
value= (MemTotal-MemFree-MemCache-MemBuff)/MemTotal
}
scale {
interval = 1000
style = ACOnline
css = "progressbar#1 progress { background-color: #ff0000;} \
progressbar#0 progress { background-color: #ffff00;}"
value = BatteryLeft/BatteryTotal
}
}
include("mpd.widget")
tray {
rows = 2
}
grid {
style = "frame"
css = "* { -GtkWidget-direction: right; }"
label { loc(1,1) }
include("cpu-temp.widget")
label { loc(1,2) }
include("lan-bps.widget")
label { loc(1,3) }
include("mb-temp.widget")
label { loc(1,4) }
include("fan-rpm.widget")
}
include("weather.widget")
include("clock.widget")
# Add the Show Desktop button
button {
value = "desktop"
action = Function "target", "ShowDesktop"
css = "* { min-height: 1.25cm; min-width: 1.25cm; }" # set icon size
}
}
#CSS
window {
-GtkWidget-direction: bottom;
}
#hidden {
-GtkWidget-visible: false;
}
button#taskbar_normal grid {
-GtkWidget-hexpand: false;
padding-right: 0px;
margin-right: 0px;
}
button#taskbar_normal image, button#taskbar_active image, button#taskbar_normal:hover image {
min-width: 0.4cm;
min-height: 0.4cm;
}
button#taskbar_normal label, button#taskbar_active label, button#taskbar_normal:hover label {
-GtkWidget-vexpand: true;
-GtkWidget-hexpand: false;
padding-left: 0.75mm;
padding-top: 0px;
padding-bottom: 0px;
font: 0.3cm Sans;
}
button#taskbar_normal , button#taskbar_active , button#taskbar_normal:hover {
padding-left: 0.75mm;
padding-top: 0.5mm;
padding-bottom: 0.5mm;
background-image: none;
border-radius: 0;
border-image: none;
-GtkWidget-hexpand: false;
}
button#taskbar_active {
background-color: #bbddff;
}
button#taskbar_normal:hover {
background-color: #cccccc;
}
button#pager_normal , button#pager_visible , button#pager_focused {
padding-left: 1.25mm;
padding-right: 1.25mm;
padding-top: 0.5mm;
padding-bottom: 0.5mm;
background-image: none;
border-radius: 0;
border-image: none;
font: 0.3cm Sans;
}
button#pager_focused {
background-color: #bbddff;
}
button#pager_preview {
background-image: none;
border-radius: 0;
border-image: none;
border-color: #000000;
border-width: 0.25mm;
color: #777777;
min-width: 5cm;
min-height: 2.8125cm;
}
grid#pager {
outline-color: #000000;
outline-style: dashed;
outline-width: 0.25mm;
}
grid#switcher_active image,
grid#switcher_active {
min-width: 1.25cm;
min-height: 1.25cm;
border-image: none;
padding: 1.25mm;
background-color: #bbddff;
border-radius: 1.25mm;
-GtkWidget-hexpand: true;
}
grid#switcher_normal image,
grid#switcher_normal {
min-width: 1.25cm;
min-height: 1.25cm;
border-image: none;
padding: 1.25mm;
-GtkWidget-direction: right;
-GtkWidget-hexpand: true;
}
window#switcher {
border-style: solid;
border-width: 0.25mm;
border-color: #000000;
border-radius: 1.25mm;
padding: 1.25mm;
-GtkWidget-hexpand: true;
}
grid#switcher {
border-radius: 1.25mm;
padding: 1.25mm;
-GtkWidget-hexpand: true;
}
button#tray_active,
button#tray_passive,
button#tray_attention {
background-image: none;
border: 0px;
padding: 0px;
margin: 0px;
border-image: none;
border-radius: 0px;
outline-style: none;
box-shadow: none;
}
button#tray_active image,
button#tray_passive image,
button#tray_attention image {
-GtkWidget-hexpand: true;
-GtkWidget-vexpand: true;
padding: 1mm;
}
progressbar {
padding-left: 0.25mm;
padding-right: 0.25mm;
-GtkWidget-vexpand: true;
-GtkWidget-direction: top;
}
progress, trough {
border-radius: 0;
border-color: #9c9c9c;
}
progress {
border-style: outset;
min-width: 2mm;
}
trough {
background-color: #a1a1a1;
border-style: inset;
min-height: 2.5mm;
min-width: 2.5mm;
}
grid#frame {
-GtkWidget-direction: bottom;
min-width: 2cm;
border-color: #9c9c9c;
border-style: groove;
border-width: 0.5mm;
padding-top: 0.25mm;
}
grid#layout {
padding: 0.25mm;
-GtkWidget-direction: right;
}
label#value {
-GtkWidget-hexpand: true;
-GtkWidget-align: 1;
padding-right: 2mm;
padding-left: 2mm;
}
image#value_icon {
min-width: 0.3cm;
min-height: 0.3cm;
}
label#mpd {
padding-top: 1mm;
padding-bottom: 1mm;
padding-left: 2mm;
padding-right: 2mm;
}
image#mpd {
min-width: 0.4cm;
min-height: 0.4cm;
padding-left: 0.5mm;
padding-right: 0.5mm;
}
button#idle_inhibit {
-GtkWidget-vexpand: true;
}
label {
font: 0.27cm Sans;
}
label#awesome {
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
@hellium6, does the latest version work as expected for you?
The showdesktop.widget works perfectly for me on AntiX Linux. My compositors are sway, labwc and wayfire.
I have been trying to figure out how showdesktop.widget works. I see that there are now 2 UserStates. And maybe that somehow targeting functions at a taskbar instead of a window, and then using the Children annotation causes the action to occur on all windows instead of a single focused window? But, why then does ShowDesktopCheckWindow and ShowDesktop have to mention target again? How global/local are UserStates? Will using them in several different widgets cause interference?
Even though I'm not completely sure how it works, I managed to change it to a 3-state behavior (focused window alone, empty desktop, all windows as they were) by changing the last condition in ShowDesktopMinimize to [!Focused | !Minimized]:
function("ShowdesktopMinimize") {
[!Minimized] UserState "on"
[Minimized] UserState "off"
[!Focused | !Minimized] Minimize
}
Which is really confusing, because I was trying to keep it 2-state (focused window alone, all windows as they were).
This is in interesting one. What showdesktop functionality needs to do is
- If we need to show desktop / hide windows: a. save the focused state of all windows (so you know which one to focus later) b. save minimized state of every window (so you know which ones to unminimize later) c. minimize all unminimized windows
- If we need to restore windows a. check if all windows are minimized, if not repeat (1) and exit b. unminimize windows that were unminimized in (1) c. focus the window that was focused in (1).
The selector between (1) and (2) is handled by function "ShowDesktop", this uses UserState of the "target" widget (which is a hidden taskbar create in the widget layout) to determine whether to perform (1) or (2).
[!UserState | Children] Function "ShowDesktopSaveFocus"
checks the UserState flag of "target" and if it's not set calls ShowDesktopSaveFocus on each child (taskbar item) of "target"
The second line does the same with "ShowDesktopMinimize" function.
ShowDesktopSaveFocus function, check the minimized state of every taskbar item and sets UserState2 accordingly. (note that this userstate of the taskbar item, not the taskbar).
ShowDesktopMinimize function sets UserState based whether the window is Minimized and minimizes the window.
The logic of unminimizing is trickier: [UserState] UserState "2:off"
clears UserState2 of the "target" taskbar. [UserState | Children] Function "ShowDesktopCheckWindow"`` run the ShowDesktopCheckWindow on all children, and this function in turn will set UserState2 of the "target" if any of the windows are still showing. (this is the bit that creates your 3-state setup, your focused window hasn't been minimized, so the UserState2 flag is set).
ShowDesktopUnminimized is called next, this is called on the "target" taskbar still, not on it's children. This function checks UserState2 and if it's set, it re-saves the current focus and then re-minimizes the windows. You didn't change ShowDesktopReminimize function, so this minimizes your focused window. If UserState2 is unset, the function calls ShowDesktopRestore and ShowDesktopRestoreFocus to perform (2) and sets UserState of "target" to tell it whether to show or hide desktop next time.
If I understand correctly, you want to change the behaviour to minimize all windows except for the focused one and then restore them? In this case the easiest way to do this would be to make the change you made and also remove [UserState | Children] Function "ShowDesktopCheckWindow"
from function ShowDesktop.
I'm impressed by the ability to fit this behavior into the semantics of the widget language with 2 bits of info per widget. Even though the stacking order is not retained.
But I'm also concerned with managing multiple widgets using UserState bits.
Could you explain the scope of the UserState bits? Are they global across all widget files? Or are they local to the current one? Meaning - will using this ShowDesktop widget interfere with some other widget that uses UserState bits for a completely different purpose?
UserStates are properties of widgets, so every widget has two user states. When an action is invoked from a widget (i.e. as a result of a click or a scroll event), the action will reference the UserStates of this widget. Moreover, it will reference a snapshot of those states, so that any changes to UserState will not affect it immediately, but only after the action is complete in it's entirety. (i.e. in a function, you can have [UserState] and [!UserState] consistently applied to the initial state, even if you toggle the state somewhere in the code). If you call other actions from within a function, they will inherit the state of the function, unless you call the action on a target (either by explicitly specifying a target or by using Children
modifier``)
I.e.:
Function("Func1") {
Function "Func2"
Function "WidgetX", "Func3"
}
In the above example, Func2 will inherit the state of Func1, but Func3 will reference the state of WidgetX.
ShowDesktop has a hidden taskbar widget named "target", and all UserStates refer to either target or it's children (taskbar items), so you're in no danger or colliding with these. Although it may be a good idea to give this widget a more complex name, in order to avoid collisions if user defined code has another widget named "target".