Skip to content

Commit 091aa0f

Browse files
committed
feat: add multi screen support
1. on wayland and ScreenFromQWindow, destory and recreate layer surafce while screenChanged 2. on x11 update to right geometry log: as title
1 parent b29f8d6 commit 091aa0f

File tree

4 files changed

+98
-45
lines changed

4 files changed

+98
-45
lines changed

example/layershell-example/main.qml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ Window {
5555
ListElement { text: "KeyboardInteractivityOnDemand"; keyboardInteractivity: DLayerShellWindow.KeyboardInteractivityOnDemand }
5656
}
5757
}
58+
59+
ComboBox {
60+
id: screenComboBox
61+
width: 200
62+
textRole: "name"
63+
anchors.left: parent.left
64+
onActivated: {
65+
root.screen = model[screenComboBox.currentIndex]
66+
}
67+
model: Application.screens
68+
}
5869
}
5970

6071
Item {

frame/layershell/qwaylandlayershellsurface.cpp

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "dlayershellwindow.h"
77
#include "qwaylandlayershellsurface_p.h"
88

9+
#include <wayland-client.h>
10+
911
#include <qwayland-wlr-layer-shell-unstable-v1.h>
1012
#include <wayland-wlr-layer-shell-unstable-v1-client-protocol.h>
1113

@@ -23,53 +25,20 @@ QWaylandLayerShellSurface::QWaylandLayerShellSurface(QtWayland::zwlr_layer_shell
2325
: QtWaylandClient::QWaylandShellSurface(window)
2426
, QtWayland::zwlr_layer_surface_v1()
2527
, m_dlayerShellWindow(DLayerShellWindow::get(window->window()))
28+
, m_window(window)
29+
, m_shell(shell)
2630
{
27-
28-
wl_output *output = nullptr;
31+
QScreen *screen = nullptr;
2932
if (m_dlayerShellWindow->screenConfiguration() == DLayerShellWindow::ScreenFromQWindow) {
30-
auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen*>(window->window()->screen()->handle());
31-
if (!waylandScreen) {
32-
qCWarning(layershellsurface) << "failed to get screen for wayland";
33-
} else {
34-
output = waylandScreen->output();
35-
}
33+
screen = m_window->window()->screen();
34+
connect(m_window->window(), &QWindow::screenChanged, this, [this](QScreen *screen){
35+
destroy();
36+
initLayerSurface(screen);
37+
});
3638
}
3739

38-
init(shell->get_layer_surface(window->waylandSurface()->object(), output, m_dlayerShellWindow->layer(), m_dlayerShellWindow->scope()));
39-
40-
set_layer(m_dlayerShellWindow->layer());
41-
connect(m_dlayerShellWindow, &DLayerShellWindow::layerChanged, this, [this, window](){
42-
set_layer(m_dlayerShellWindow->layer());
43-
window->waylandSurface()->commit();
44-
});
45-
46-
set_anchor(m_dlayerShellWindow->anchors());
47-
connect(m_dlayerShellWindow, &DLayerShellWindow::anchorsChanged, this,[this, window](){
48-
trySetAnchorsAndSize();
49-
});
50-
51-
set_exclusive_zone(m_dlayerShellWindow->exclusionZone());
52-
connect(m_dlayerShellWindow, &DLayerShellWindow::exclusionZoneChanged, this,[this, window](){
53-
set_exclusive_zone(m_dlayerShellWindow->exclusionZone());
54-
window->waylandSurface()->commit();
55-
});
56-
57-
set_margin(m_dlayerShellWindow->topMargin(), m_dlayerShellWindow->rightMargin(), m_dlayerShellWindow->bottomMargin(), m_dlayerShellWindow->leftMargin());
58-
connect(m_dlayerShellWindow, &DLayerShellWindow::marginsChanged, this, [this](){
59-
set_margin(m_dlayerShellWindow->topMargin(), m_dlayerShellWindow->rightMargin(), m_dlayerShellWindow->bottomMargin(), m_dlayerShellWindow->leftMargin());
60-
});
61-
62-
set_keyboard_interactivity(m_dlayerShellWindow->keyboardInteractivity());
63-
connect(m_dlayerShellWindow, &DLayerShellWindow::keyboardInteractivityChanged, this, [this, window](){
64-
set_keyboard_interactivity(m_dlayerShellWindow->keyboardInteractivity());
65-
window->waylandSurface()->commit();
66-
});
67-
68-
calcAndSetRequestSize(window->surfaceSize());
69-
70-
if (m_requestSize.isValid()) {
71-
set_size(m_requestSize.width(), m_requestSize.height());
72-
}
40+
initLayerSurface(screen);
41+
initConnections();
7342
}
7443

7544
QWaylandLayerShellSurface::~QWaylandLayerShellSurface()
@@ -156,4 +125,66 @@ void QWaylandLayerShellSurface::attachPopup(QtWaylandClient::QWaylandShellSurfac
156125
}
157126
}
158127

128+
void QWaylandLayerShellSurface::initLayerSurface(QScreen *screen)
129+
{
130+
wl_output *output = nullptr;
131+
auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen*>(m_window->window()->screen()->handle());
132+
133+
if (!waylandScreen) {
134+
qCWarning(layershellsurface) << "failed to get screen for wayland";
135+
} else {
136+
output = waylandScreen->output();
137+
}
138+
139+
auto wl_surface = m_window->waylandSurface()->object();
140+
wl_surface_attach(wl_surface, nullptr, 0, 0);
141+
142+
m_configured = false;
143+
init(m_shell->get_layer_surface(wl_surface, output, m_dlayerShellWindow->layer(), m_dlayerShellWindow->scope()));
144+
145+
set_layer(m_dlayerShellWindow->layer());
146+
set_anchor(m_dlayerShellWindow->anchors());
147+
set_exclusive_zone(m_dlayerShellWindow->exclusionZone());
148+
set_margin(m_dlayerShellWindow->topMargin(), m_dlayerShellWindow->rightMargin(), m_dlayerShellWindow->bottomMargin(), m_dlayerShellWindow->leftMargin());
149+
150+
calcAndSetRequestSize(m_window->surfaceSize());
151+
if (m_requestSize.isValid()) {
152+
set_size(m_requestSize.width(), m_requestSize.height());
153+
}
154+
155+
window()->resizeFromApplyConfigure(m_pendingSize);
156+
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
157+
window()->handleExpose(QRect(QPoint(), m_pendingSize));
158+
#else
159+
window()->sendRecursiveExposeEvent();
160+
#endif
161+
m_window->waylandSurface()->commit();
162+
}
163+
164+
void QWaylandLayerShellSurface::initConnections()
165+
{
166+
connect(m_dlayerShellWindow, &DLayerShellWindow::layerChanged, this, [this](){
167+
set_layer(m_dlayerShellWindow->layer());
168+
m_window->waylandSurface()->commit();
169+
});
170+
171+
connect(m_dlayerShellWindow, &DLayerShellWindow::anchorsChanged, this,[this](){
172+
trySetAnchorsAndSize();
173+
});
174+
175+
connect(m_dlayerShellWindow, &DLayerShellWindow::exclusionZoneChanged, this,[this](){
176+
set_exclusive_zone(m_dlayerShellWindow->exclusionZone());
177+
m_window->waylandSurface()->commit();
178+
});
179+
180+
connect(m_dlayerShellWindow, &DLayerShellWindow::marginsChanged, this, [this](){
181+
set_margin(m_dlayerShellWindow->topMargin(), m_dlayerShellWindow->rightMargin(), m_dlayerShellWindow->bottomMargin(), m_dlayerShellWindow->leftMargin());
182+
});
183+
184+
connect(m_dlayerShellWindow, &DLayerShellWindow::keyboardInteractivityChanged, this, [this](){
185+
set_keyboard_interactivity(m_dlayerShellWindow->keyboardInteractivity());
186+
m_window->waylandSurface()->commit();
187+
});
188+
}
189+
159190
DS_END_NAMESPACE

frame/layershell/qwaylandlayershellsurface_p.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,16 @@ class QWaylandLayerShellSurface : public QtWaylandClient::QWaylandShellSurface,
3636
void calcAndSetRequestSize(QSize requestSize);
3737
bool anchorsSizeConflict() const;
3838
void trySetAnchorsAndSize();
39+
void initLayerSurface(QScreen* screen);
40+
void initConnections();
3941

42+
private:
4043
DLayerShellWindow* m_dlayerShellWindow;
4144
QSize m_pendingSize;
4245
QSize m_requestSize;
4346
bool m_configured = false;
47+
QtWaylandClient::QWaylandWindow *m_window;
48+
QtWayland::zwlr_layer_shell_v1 *m_shell;
4449
};
4550

4651
DS_END_NAMESPACE

frame/layershell/x11dlayershellemulation.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ LayerShellEmulation::LayerShellEmulation(QWindow* window, QObject *parent)
4949
}
5050

5151
connect(nowScreen, &QScreen::geometryChanged, this, &LayerShellEmulation::onPositionChanged);
52+
onPositionChanged();
53+
QMetaObject::invokeMethod(this, &LayerShellEmulation::onExclusionZoneChanged, Qt::QueuedConnection);
5254
});
5355

5456
// connect(m_dlayerShellWindow, &DS_NAMESPACE::DLayerShellWindow::keyboardInteractivityChanged, this, &LayerShellEmulation::onKeyboardInteractivityChanged);
@@ -68,6 +70,7 @@ void LayerShellEmulation::onLayerChanged()
6870
auto xcbWindow = dynamic_cast<QNativeInterface::Private::QXcbWindow*>(m_window->handle());
6971
switch (m_dlayerShellWindow->layer()) {
7072
case DLayerShellWindow::LayerBackground: {
73+
m_window->setFlags(m_window->flags() & ~Qt::WindowStaysOnBottomHint);
7174
xcbWindow->setWindowType(QNativeInterface::Private::QXcbWindow::Desktop);
7275
break;
7376
}
@@ -78,13 +81,15 @@ void LayerShellEmulation::onLayerChanged()
7881
break;
7982
}
8083
case DLayerShellWindow::LayerTop: {
84+
m_window->setFlags(m_window->flags() & ~Qt::WindowStaysOnBottomHint);
8185
xcbWindow->setWindowType(QNativeInterface::Private::QXcbWindow::Dock);
8286
break;
8387
}
8488
case DLayerShellWindow::LayerOverlay: {
8589
// on deepin Notification will be influenced by exclusionZone,
8690
// while plasma works all right, maybe deepin kwin bug?
8791
// FIXME: fix above
92+
m_window->setFlags(m_window->flags() & ~Qt::WindowStaysOnBottomHint);
8893
xcbWindow->setWindowType(QNativeInterface::Private::QXcbWindow::Notification);
8994
break;
9095
}
@@ -95,8 +100,9 @@ void LayerShellEmulation::onPositionChanged()
95100
{
96101
auto anchors = m_dlayerShellWindow->anchors();
97102
auto screen = m_window->screen();
98-
auto x = (screen->geometry().right() - m_window->width()) / 2;
99-
auto y = (screen->geometry().height() - m_window->height()) / 2;
103+
auto screenRect = screen->geometry();
104+
auto x = screenRect.left() + (screenRect.width() - m_window->width()) / 2;
105+
auto y = screenRect.top() + (screenRect.height() - m_window->height()) / 2;
100106
if (anchors & DLayerShellWindow::AnchorRight) {
101107
// https://doc.qt.io/qt-6/qrect.html#right
102108
x = (screen->geometry().right() + 1 - m_window->width() - m_dlayerShellWindow->rightMargin());

0 commit comments

Comments
 (0)