1010#include < qqmllist.h>
1111#include < qquickwindow.h>
1212#include < qscreen.h>
13+ #include < qtimer.h>
1314#include < qtmetamacros.h>
1415#include < qtypes.h>
1516#include < xcb/xproto.h>
1617
1718#include " ../core/generation.hpp"
1819#include " ../core/panelinterface.hpp"
1920#include " ../core/proxywindow.hpp"
21+ #include " ../core/qmlscreen.hpp"
2022#include " util.hpp"
2123
2224class XPanelStack {
@@ -56,6 +58,17 @@ class XPanelStack {
5658 }
5759 }
5860
61+ void updateLowerDimensions (XPanelWindow* exclude) {
62+ auto & panels = this ->mPanels [EngineGeneration::findObjectGeneration (exclude)];
63+
64+ // update all panels lower than the one we start from
65+ auto found = false ;
66+ for (auto * panel: panels) {
67+ if (panel == exclude) found = true ;
68+ else if (found) panel->updateDimensions (false );
69+ }
70+ }
71+
5972private:
6073 std::map<EngineGeneration*, QList<XPanelWindow*>> mPanels ;
6174};
@@ -151,9 +164,8 @@ qint32 XPanelWindow::exclusiveZone() const { return this->mExclusiveZone; }
151164void XPanelWindow::setExclusiveZone (qint32 exclusiveZone) {
152165 if (this ->mExclusiveZone == exclusiveZone) return ;
153166 this ->mExclusiveZone = exclusiveZone;
154- const bool wasNormal = this ->mExclusionMode == ExclusionMode::Normal;
155167 this ->setExclusionMode (ExclusionMode::Normal);
156- if (wasNormal) this ->updateStrut ();
168+ this ->updateStrut ();
157169 emit this ->exclusiveZoneChanged ();
158170}
159171
@@ -225,14 +237,16 @@ void XPanelWindow::connectScreen() {
225237 this ->mTrackedScreen ,
226238 &QScreen::geometryChanged,
227239 this ,
228- &XPanelWindow::updateDimensions
240+ &XPanelWindow::updateDimensionsSlot
229241 );
230242 }
231243
232244 this ->updateDimensions ();
233245}
234246
235- void XPanelWindow::updateDimensions () {
247+ void XPanelWindow::updateDimensionsSlot () { this ->updateDimensions (); }
248+
249+ void XPanelWindow::updateDimensions (bool propagate) {
236250 if (this ->window == nullptr || this ->window ->handle () == nullptr || this ->mScreen == nullptr )
237251 return ;
238252
@@ -302,7 +316,15 @@ void XPanelWindow::updateDimensions() {
302316 }
303317
304318 this ->window ->setGeometry (geometry);
305- this ->updateStrut ();
319+ this ->updateStrut (propagate);
320+
321+ // AwesomeWM incorrectly repositions the window without this.
322+ // See https://github.com/polybar/polybar/blob/f0f9563ecf39e78ba04cc433cb7b38a83efde473/src/components/bar.cpp#L666
323+ QTimer::singleShot (0 , this , [this , geometry]() {
324+ // forces second call not to be discarded as duplicate
325+ this ->window ->setGeometry ({0 , 0 , 0 , 0 });
326+ this ->window ->setGeometry (geometry);
327+ });
306328}
307329
308330void XPanelWindow::updatePanelStack () {
@@ -314,7 +336,10 @@ void XPanelWindow::updatePanelStack() {
314336}
315337
316338void XPanelWindow::getExclusion (int & side, quint32& exclusiveZone) {
317- if (this ->mExclusionMode == ExclusionMode::Ignore) return ;
339+ if (this ->mExclusionMode == ExclusionMode::Ignore) {
340+ exclusiveZone = 0 ;
341+ return ;
342+ }
318343
319344 auto & anchors = this ->mAnchors ;
320345 if (anchors.mLeft || anchors.mRight || anchors.mTop || anchors.mBottom ) {
@@ -344,7 +369,7 @@ void XPanelWindow::getExclusion(int& side, quint32& exclusiveZone) {
344369 }
345370}
346371
347- void XPanelWindow::updateStrut () {
372+ void XPanelWindow::updateStrut (bool propagate ) {
348373 if (this ->window == nullptr || this ->window ->handle () == nullptr ) return ;
349374 auto * conn = x11Connection ();
350375
@@ -359,13 +384,19 @@ void XPanelWindow::updateStrut() {
359384 return ;
360385 }
361386
387+ // Due to missing headers it isn't even possible to do this right.
388+ // We assume a single xinerama monitor with a matching size root.
389+ auto screenGeometry = this ->window ->screen ()->geometry ();
390+ auto horizontal = side == 0 || side == 1 ;
391+
362392 auto data = std::array<quint32, 12 >();
363393 data[side] = exclusiveZone;
364394
365- // https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm45573693101552
366- // assuming "specified in root window coordinates" means relative to the window geometry
367- // in which case only the end position should be set, to the opposite extent.
368- data[side * 2 + 5 ] = side == 0 || side == 1 ? this ->window ->height () : this ->window ->width ();
395+ auto start = horizontal ? screenGeometry.top () + this ->window ->y ()
396+ : screenGeometry.left () + this ->window ->x ();
397+
398+ data[4 + side * 2 ] = start;
399+ data[5 + side * 2 ] = start + (horizontal ? this ->window ->height () : this ->window ->width ());
369400
370401 xcb_change_property (
371402 conn,
@@ -388,6 +419,8 @@ void XPanelWindow::updateStrut() {
388419 12 ,
389420 data.data ()
390421 );
422+
423+ if (propagate) XPanelStack::instance ()->updateLowerDimensions (this );
391424}
392425
393426void XPanelWindow::updateAboveWindows () {
0 commit comments