Skip to content

Conversation

@kronn
Copy link
Contributor

@kronn kronn commented Dec 3, 2017

My plan is grand and all-encompassing: list all occupied workspaces.

So far, I list all workspaces not currently visible on another workspace. I would be very grateful for input on how to resolve this to a usable state...

This is supposed to fix #874

TEAMEDIT:
Fixes #1444
Fixes #1033

@NBonaparte
Copy link
Member

NBonaparte commented Dec 4, 2017

So far, the best way I can think of to solve most of the issues is by linking each window with its desktop. This would involve changing m_clientlist to vector<pair<xcb_window_t, unsigned int>>. Now, removing and tracking windows should be easier, as we know which desktop it was last in and can remove the corresponding value from m_occupied_desktops.
Speaking of which, it might be easier to have m_occupied_desktops as a tally system for each desktop, with the index corresponding to the desktop number and the value to the number of windows within that desktop.

For window removals, you should remove the desktop from m_occupied_desktops here (but also know which one it was in beforehand):
https://github.com/jaagr/polybar/blob/17f1f19012e486bbdd82be8093b620a4e098de37/src/modules/xworkspaces.cpp#L132-L135

With the system above, your first commit should help to track changes in each desktop, as we now know which desktop it came from and where it is currently.

@kronn
Copy link
Contributor Author

kronn commented Dec 4, 2017

I am very sorry and feel like wasting your time. Full disclosure at this point: I know how to program, but my C++ is limited to the two commits you already saw. Mostly, I am missing a way to output the state of certain datastructures, so I can see what exactly is known to polybar. Without this, I have the nagging feeling to miss something obvious.

The type-change you proposed surpasses my skill-level. The compiler output tells me that I hurt it badly, but I cannot make sense of this so far.

I feel like there is something simple missing, since I see (in my bar) that only the desktops of other visible, but unfocussed viewports are not occupied. Since I can see them, I known there are windows present.

A short test seems to prove my assumption: If I only have one viewport/screen, then I get the list of occupied desktops shown correctly. Just switching to one big-ass monitor might be a solution, but it is both too expensive and unsatisfying 😁 One thing that does not work correctly yet is the removal of the "occupied"-state, but this is something that I expect from the current version.

Also, just to clarify the terminology: with a tally system, you mean a datastructure to keep track of the windows/clients of each desktop. Something like (in JSON-notation)

{
  web: ['chrome'],
  work: ['vim', 'emacs', 'notepad'],
  chat: ['pidgin', 'skype']
}

where all the strings are the internal ids of the corresponding windows-titles and desktop-labels?

Tomorrow, I will try to get the removal working with the current datastructures. Then I have at least a working version for a simgle-monitor setup. This won't be enough for the complete feature I have in mind, but I need small steps I can actually reach...

@kronn
Copy link
Contributor Author

kronn commented Dec 13, 2017

After reading and experimenting a bit, I was able to change the type rather easily. While doing so, I notice how right this feels. Thanks for the advice, @NBonaparte. Also, listening to the compiler is useful during such refactoring, it turns out. 😉 The current state (esp. ed6db8c and 2483681) should keep track of windows in their desktops/workspaces.

For my local testing, I also readded the "sending windows to certain desktops"-function. I have the feeling that it will be not needed anymore, but it does not seem to hurt for now.

At this point I also feel like I might have introduced a race condition, if two bars are using the xworkspaces module. Since my knowledge of the internal structure of polybar is limited: could the current clear/rebuild/sort/unique-dance I do with the m_occupied_workspaces be a victim to reentrancy? Is the datastructure shared between instances of polybar? I would say "no", but I really want to make sure, just in case.

Lastly, I noticed an odd behaviour: I have windows on desktops 5, 6, 7 and 8. When I go through them one by one, the desktop before the previous one (depending on the order I jump), is marked unoocupied, although there is still a window present. If you can spot the error right away, I would be grateful for pointers. Otherwise, I will research that in the coming days.

@NBonaparte
Copy link
Member

There should be no race condition, as all the data structures for each module are unique.

I cannot seem to reproduce your issue. Is there a specific procedure to produce this?

@kronn
Copy link
Contributor Author

kronn commented Dec 16, 2017

Race Conditions: okay. I thought and hoped so, just wanted to make sure.

Odd Behaviour: Maybe I looked at a incomplete build... I cannot reproduce it either, now.

In my own personal agenda, I have two open topics:

  1. Showing occupied workspaces on other visible workspaces as occupied (or maybe as "on visible, yet not active")
    • showing them as occupied instead of empty seens way easier than a new state "visible".
    • therefore I will only show them as occupied, which is at least correct.
    • after a bit of research, "just collecting the occupied" desktop seems more complicated than I thought. Either the underlying X11-libs or my WM (xmonad) seem to be clever and only return the windows that are hidden. The others are somehow not in the _NET_CLIENT_LIST.
  2. I rebuild the m_occupied_desktops a lot. I leave the structure, but clear and rebuild every time.
    • this seems less than ideal, mostly a waste of CPU-cycles
    • OTOH, maybe is fast enough and handling the life-cycle of each window is more complicated to maintain (and create in the first place) than just rebuilding this vector<unsigned int> of mostly up to 10 elements.

While 1. is a personal must for this feature to be complete, 2. is more a question that a task. Which route would you choose?

@NBonaparte
Copy link
Member

For 2:

The tally/counting system IMO should solve this in a simple manner. Just to clarify my idea, the vector would have an element per desktop, with the number of windows in that specific desktop as the value. (Maybe change the name to m_desktop_client_count or something else that makes more sense.)

For example, let's say we have 3 windows on desktop 1, 2 on desktop 2, and no other windows. The vector would be [3, 2, 0, 0, 0] (for 5 desktops). Now we create another window on desktop 1. When we track the window (line 157), we would also increment the first element (corresponding to the first desktop) by 1. If we close any window, we should also decrement the element by 1 (after 148), and since we know which desktop it was in (win_desktop.second) this shouldn't be too hard.

If a window moves to a different desktop, we should be able to track that by listening for _NET_WM_DESKTOP in the handler, since we already requested for property changes for it. Then we should be able to change the window count appropriately, and update the desktop number in m_clientlist.

@kronn
Copy link
Contributor Author

kronn commented Dec 17, 2017

Well, my personal 1. is a bug in xmonad and therefore outside of the scope of this PR (see linked issue).

As for 2: Thanks for the clarification. I think I misunderstood what you had in mind.

The pure counter sounds good at first, but - coming from a web-app background - I fear maintaining a counter for a long time. Maybe it's premature optimization or being burnt by a web-environment, but I want to recalculate the whole m_desktop_client_count if we ever reach -1 somewhere. This forces the recalculation into its own method. I would move the current recalc-part there and output an info-logging if that happens. This way, we can keep an eye on it. What do you think of this?

Tomorrow, I will work on moving m_occupied_desktops to your proposed m_desktop_client_count. Since git does not forget old code, we can decide about handling the aforementioned edge-case later.

@kronn
Copy link
Contributor Author

kronn commented Dec 18, 2017

By now, I distrust XMonads ability to be a good EWMH-citizen. With the pure counter-implementation I now pushed, it is far easier to mark a workspace as occupied. Keeping track of the window-count seems sadly a lost cause. XMonad advertises changes in the desktop-names which might trigger a recount. Also, the Tally seems to be empty every time a recount is in order. Since I only empty it before the recount, I am a bit confused.

I pushed the version with debugging info-log statements, so you can see where I wanted to know more. Judging from my local output, I see several (4) entries to the recount-function. The xworkspaces-modules is only active in one bar.

The fresh count seems to always be accurate (within the limits of Xmonads current implementation). Keeping a continuous count seems to not work. Or maybe it does, but the frequent changes to the _NET_DESKTOP_NAMES sabotage that.

The current version needs less logging in order to be mergeable. This information is not even useful at a trace-level in normal operations. Other than that, it seems to work okay for me. The frequent desktop-name changes trigger enough complete recounts to keep the score correct.

Therefore I would be happy if anyone with different WM could test this. Who could do that?

@NBonaparte
Copy link
Member

I use bspwm and @patrick96 uses hlwm (I think), so we could test it out on those WMs, as well as i3 and maybe openbox. Others are also welcome to test this.

@kronn
Copy link
Contributor Author

kronn commented Dec 20, 2017

I think that the bar works for me since XMonad issues a metric ****ton of changes to the rather static _NET_DESKTOP_NAMES. Those trigger a complete recount of clients/desktop.

I consider this buggy behaviour by the WM, although the compiled polybar-binary does not even care, it just performs. I seriously wonder how other WMs handle this. I will try out another WM (openbox, most likely) tomorrow to get a feeling for this. Since bspwm and i3 have their own modules, they are not as affected as those relying on EWMH...

hlwm is not in my Ubuntu sources. While this could be remedied, I prefer to go one step at a time :-)

Then again, maybe it's perfectly normal to change the desktop-count and their names all the time. If that would be the case across WMs I would maybe rethink xworkspaces_module::rebuild_desktops(). Well, maybe... I'm missing data here.

@mbrgm
Copy link

mbrgm commented Mar 6, 2018

Any progress on this?

@kronn
Copy link
Contributor Author

kronn commented Mar 7, 2018

@mbrgm I had very little time lately to work on this. From trying my local version I see that the count is sometimes off or even completely missing (all WS appear empty). When I then "switch" to the same WS again, everything is updated. I think that I handle the X events a little wrong. This may be rooted in my patched version of xmonad. Or something else...

Either way, debugging this was not a priority lately, due to work and such. I will see if I can get to it in the coming week. At the very least I will rebase my local branch onto current master.

Would you be able and willing to compile and test this version yourself?

@kronn
Copy link
Contributor Author

kronn commented Mar 7, 2018

Oh, and it segfaults all the time. I really need to take the time and fix that. Right now, I have a shortcut to restart polybar because of the many crashes. While convenient for me, I would not impose that on everyone.

@mbrgm
Copy link

mbrgm commented Mar 8, 2018

Would you be able and willing to compile and test this version yourself?

Yup, I'm fine with that. Also no problem about segfaulting. Could you push your branch and post a link?

@kronn kronn force-pushed the list-occupied-workspaces branch from 68804f5 to cebc7fc Compare March 12, 2018 13:53
@kronn
Copy link
Contributor Author

kronn commented Mar 12, 2018

@mbrgm I rebased my branch onto the current master and pushed it to https://github.com/kronn/polybar/tree/list-occupied-workspaces

Currently, I have the following problems:

  • sometimes crashing, seems to coincide with changes in the "title" of a window.
  • active WS is sometimes only updated after second switch to a WS and then switching back to a previous state
  • I feel like the counting is done wrong, but I might just lack understanding

The current build emits a metric ton of logging-output on info-level, whenever some counting or checking is done. Although this clearly is debugging-information, I made these info-level to have them better readable for now. In a final version, I would remove them entirely or reduce them to very few debug-level loggings.

I would like to get some information and feedback from running this under another EWMH-WM than a patched xmonad.

My setup is:

  • 1 laptop monitor and two external monitors via docking station
  • polybar head + my extensions
  • xmonad 0.13 with some changes to the EWMH-adapter, to habe windows always report the correct WS. Without that, xmonad always pretends that all visible windows are on the current WS to help gnome-panel. See referenced PR above (2017-12-17).

@jonhoo
Copy link
Contributor

jonhoo commented Mar 12, 2018

I wonder if the crash you're seeing is related to #1033...

@mbrgm
Copy link

mbrgm commented Mar 12, 2018

To be honest, as it's been silent in here and I needed a working solution quickly, I used the weekend to switch to writing polybar-formatted output to a fifo using xmonad's event log hook, which works just fine and seems to be pretty stable. If someone is interested in the solution, I can post a gist.

@kronn
Copy link
Contributor Author

kronn commented Mar 12, 2018

@mbrgm I will continue with an EWMH-solution, but you should contribute your solution to https://github.com/x70b1/polybar-scripts

if you don't want to contribute there, a gist would be very welcome.

@NBonaparte NBonaparte changed the title List occupied workspaces [WIP] feat(xworkspaces): List occupied workspaces Mar 25, 2018
@taschenb
Copy link
Contributor

@kronn Do you still work on a solution for that? I prototyped the discussion from this pull request and currently running it in herbstluftwm without any issues. feat/occupied-workspaces. I hope you find it helpful and continue your work.

@kronn
Copy link
Contributor Author

kronn commented Jun 18, 2018

@taschenb In general, I think I am done. I get segfaults a lot, but those can be rooted in the interaction between xmonad and polybar.

I will take a look at your solution this week and try to finish this PR up. All I wanted was solution that works not only for me but for at least one other WM.

@swillner
Copy link

There were some issues in the code (e.g. using std::set_difference on unsorted vectors), so I took the liberty to fix these and open a new PR (based on @kronn's changes for the credit): #1429 ;)
In there, I switched to a std::vector<bool> to just track if a workspace is occupied rather than counting clients as ewmh_util::get_desktop_from_window has to be called for each client in rebuild_clientlist() anyway...
I have only tested it for xmonad, for which it works fine.

@jonhoo
Copy link
Contributor

jonhoo commented Sep 19, 2018

This is a little orthogonal, but it would be awesome if this feature could also be extended to support just highlighting occupied workspaces differently, as opposed to only listing occupied workspaces.

@swillner
Copy link

hmm, that would easily be done. how would the additional information (number of clients per workspace) be used?

@jonhoo
Copy link
Contributor

jonhoo commented Sep 19, 2018

Well, specifically, I'd like to be able to have workspaces that have something on them styled differently than those that are empty. Basically, I want label-occupied to work :p

@swillner
Copy link

ah, well that is the whole purpose of this PR ;)
I thought, you wanted them styled depending on the exact number of clients rather than just if they are occupied or not (which is already done by this PR)

@Lomadriel
Copy link
Member

Running the current version of the branch, I get a "laggy" behaviour. Sometimes when I switch the workspace, polybar does not reflect the current workspace correctly. When I switch the next workspace (or the same one again), polybar is updated again correctly. I vaguely remember that I had this before, but I did not search my previous commits (those may contain a reference to this if I fixed that explicitely).

Damn, I'll try to reproduce and fix that.

@kronn
Copy link
Contributor Author

kronn commented Aug 21, 2019

I get a "laggy" behaviour.

Damn, I'll try to reproduce and fix that.

This might be a xmonad-issue. Also, I only had this before lunch, afterwards, it was fine. I did not, however, restart polybar or change the monitor-setup. Right now, it happened again. This time, I switched from docking-station to laptop-mode and therefore also restarted polybar.

@Lomadriel
Copy link
Member

This might be a xmonad-issue. Also, I only had this before lunch, afterwards, it was fine. I did not, however, restart polybar or change the monitor-setup. Right now, it happened again. This time, I switched from docking-station to laptop-mode and therefore also restarted polybar.

I'll try under xmonad since I can't reproduce that issue under i3wm.

@Lomadriel
Copy link
Member

Lomadriel commented Aug 21, 2019

I'm unable to reproduce your issue. I think this issue might be a problem of concurrent access. :/

I may have a solution to debug that but I'll need your help.

When you have time, can you try to reproduce this issue while running polybar in rr.
Use the following command: rr record --chaos [polybar cmd].
Then run rr pack before modifying anything (like the config, the executable, …).
Zip the folder (it should be printed in your terminal when you run pack) and send it to me via a mail or whatever you want.

It may be possible that you can't reproduce this problem while running polybar into rr since it can't simulate multithread but that it's worth a try.

@kronn
Copy link
Contributor Author

kronn commented Aug 22, 2019

I'll give it a try later today.

If the problem is not reproducible with rr, then I can just run it in rr all the time and solve it this way 😂

@kronn
Copy link
Contributor Author

kronn commented Aug 23, 2019

I have not encountered the laggy behaviour again, even without using rr.

@kronn
Copy link
Contributor Author

kronn commented Sep 3, 2019

I have used several different monitor setups and not encountered the laggy behaviour anymore. If it comes up again, I would file a separate bug. From my point of view, this PR is therefore ready for a final review.

Do you see #1849 as a hard prerequisite or is there anything else blocking this?

@Lomadriel
Copy link
Member

No I don't see #1849 as a prerequisite.
I'll review that asap.

Copy link
Member

@Lomadriel Lomadriel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@dkasak
Copy link
Contributor

dkasak commented Oct 2, 2019

Just wanted to say I've also been using the newest patch set for this in the last few weeks and things are working smoothly.

@kronn kronn requested a review from patrick96 October 2, 2019 09:51
@codecov
Copy link

codecov bot commented Oct 21, 2019

Codecov Report

Merging #882 into master will increase coverage by 11.81%.
The diff coverage is n/a.

Impacted file tree graph

@@             Coverage Diff             @@
##           master     #882       +/-   ##
===========================================
+ Coverage   27.02%   38.83%   +11.81%     
===========================================
  Files          52       63       +11     
  Lines        2139     2552      +413     
===========================================
+ Hits          578      991      +413     
  Misses       1561     1561
Flag Coverage Δ
#unittests 38.83% <ø> (+11.81%) ⬆️
Impacted Files Coverage Δ
tests/unit_tests/utils/string.cpp 100% <0%> (ø)
tests/unit_tests/utils/color.cpp 100% <0%> (ø)
tests/unit_tests/utils/memory.cpp 100% <0%> (ø)
tests/unit_tests/utils/file.cpp 100% <0%> (ø)
tests/unit_tests/utils/scope.cpp 100% <0%> (ø)
tests/unit_tests/components/command_line.cpp 100% <0%> (ø)
tests/unit_tests/components/parser.cpp 100% <0%> (ø)
tests/unit_tests/components/builder.cpp 100% <0%> (ø)
tests/unit_tests/components/config_parser.cpp 100% <0%> (ø)
tests/unit_tests/utils/math.cpp 100% <0%> (ø)
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 211b0bb...e04b7dc. Read the comment docs.

Copy link
Member

@patrick96 patrick96 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks in order. This is a very clean implementation, good work everyone!

I had some issues on i3 but I think that's an i3 issue since it didn't send _NET_CURRENT_DESKTOP when I switched to a workspace in the beginning.

Another thing that might be interesting is what happens when _NET_WM_DESKTOP is not set or when it is set to 0xFFFFFFFF. The 0xFFFFFFFF case should be easy enough as long as there aren't a billion desktops ;)

If _NET_WM_DESKTOP is not set though, I suspect get_desktop_from_window will return 0 meaning all windows without _NET_WM_DESKTOP would mark the first workspace as occupied. I think this is fine since most WMs will set that property after the fact to move windows into workspaces.

@patrick96 patrick96 merged commit 52f0623 into polybar:master Oct 21, 2019
@patrick96
Copy link
Member

Awesome!

After two years we finally did it! 😄

Thank you very much @kronn, @dnnr and @Lomadriel for putting in time and effort and working together on this. We're very excited to have this in the repo.

❤️

@kronn
Copy link
Contributor Author

kronn commented Oct 21, 2019

You cannot imagine the joy this merge brings to me. In the end, very little of my code remains (so it feels), but I have the feeling that I helped with this features. Also, I can now switch back to master and get other features. :-)

@kronn kronn deleted the list-occupied-workspaces branch October 21, 2019 08:32
@jonhoo
Copy link
Contributor

jonhoo commented Oct 21, 2019

Excellent work everyone!

Is there documentation anywhere for how this feature can be used in styling?

@patrick96
Copy link
Member

The documentation was actually already there before the feature was implemented 😉 https://github.com/polybar/polybar/wiki/Module:-xworkspaces

@jonhoo
Copy link
Contributor

jonhoo commented Oct 24, 2019

After building polybar with this merged, it looks like my list of workspaces is now always empty at startup time (i.e., when polybar is started by my WM). If I then manually restart it a bit later, the workspaces appear as usual. Is that expected behavior?

@patrick96
Copy link
Member

@jonhoo could you please open a new issue with this. This often happens when polybar is started too early, I don't think this PR causes it, but let's see.

@jonhoo
Copy link
Contributor

jonhoo commented Oct 24, 2019

@patrick96 it's hard to reproduce reliably, but files #1915

doronbehar added a commit to doronbehar/polybar that referenced this pull request Nov 13, 2019
…eaudio-port

* 'master' of https://github.com/polybar/polybar: (37 commits)
  github: Add subreddit as contact link
  aur: Update maintainer
  Update PKGBUILD for 3.4.1
  ipc: Remove unused global setting
  build: Move all possible variables into settings.cpp
  fix(http): Pass char* as CURLOPT_USERAGENT
  build: Move non-macro variables into settings.cpp
  Update spec file
  clang-format
  bar: Make module separator a label
  build: drop python2
  fix(build): Ignore noexcept-type for malloc_ptr_t
  travis: update to bionic
  fix(backlight): Use 'brightness' with amdgpu_bl0
  fix(bar): Configure window before remapping
  controller: Print error for duplicate modules (polybar#1534)
  feat(xworkspaces): Support occupied workspaces (polybar#882)
  temperature: Use format-warn at warn-temperature not after (polybar#1897)
  feat(pulse): Show volume in decibels (polybar#1894)
  fix(ipc): Update bar when making bar visible
  ...
patrick96 added a commit to patrick96/polybar that referenced this pull request Dec 5, 2020
If two WM events arrive withing 25ms of one-another, the second one does
not trigger a bar update.
The module state is still correct, it is just not reflected in the bar.

This somehow caused updates being swallowed in fluxbox, but only after
PR polybar#882 was merged, even though that 25ms restriction existed long
before that.

Fixes polybar#2272
patrick96 added a commit that referenced this pull request Dec 5, 2020
If two WM events arrive withing 25ms of one-another, the second one does
not trigger a bar update.
The module state is still correct, it is just not reflected in the bar.

This somehow caused updates being swallowed in fluxbox, but only after
PR #882 was merged, even though that 25ms restriction existed long
before that.

Fixes #2272
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

segfault when building the xworkspace-nodes from desktop-labels xworkspaces segfault xworkspace Improvements