Skip to content

Commit 95245cb

Browse files
committed
x11/panelwindow: fix strut start/end, patch around awesome, resize all panels
1 parent 94e881e commit 95245cb

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

src/x11/panel_window.cpp

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
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

2224
class 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+
5972
private:
6073
std::map<EngineGeneration*, QList<XPanelWindow*>> mPanels;
6174
};
@@ -151,9 +164,8 @@ qint32 XPanelWindow::exclusiveZone() const { return this->mExclusiveZone; }
151164
void 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

308330
void XPanelWindow::updatePanelStack() {
@@ -314,7 +336,10 @@ void XPanelWindow::updatePanelStack() {
314336
}
315337

316338
void 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

393426
void XPanelWindow::updateAboveWindows() {

src/x11/panel_window.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,16 @@ class XPanelWindow: public ProxyWindowBase {
7979

8080
private slots:
8181
void xInit();
82-
void updateDimensions();
8382
void updatePanelStack();
83+
void updateDimensionsSlot();
8484

8585
private:
8686
void connectScreen();
8787
void getExclusion(int& side, quint32& exclusiveZone);
88-
void updateStrut();
88+
void updateStrut(bool propagate = true);
8989
void updateAboveWindows();
9090
void updateFocusable();
91+
void updateDimensions(bool propagate = true);
9192

9293
QPointer<QScreen> mTrackedScreen = nullptr;
9394
bool mAboveWindows = true;

0 commit comments

Comments
 (0)