KWin
Loading...
Searching...
No Matches
screenedgeshowtest.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5*/
6#include "utils/xcbutils.h"
7
8#include <QApplication>
9#include <QCheckBox>
10#include <QHBoxLayout>
11#include <QMenu>
12#include <QPlatformSurfaceEvent>
13#include <QPushButton>
14#include <QScreen>
15#include <QTimer>
16#include <QToolButton>
17#include <QWidget>
18#include <QWindow>
19#include <private/qtx11extras_p.h>
20
21#include <KWindowSystem>
22
23#include <KWayland/Client/connection_thread.h>
24#include <KWayland/Client/plasmashell.h>
25#include <KWayland/Client/registry.h>
26#include <KWayland/Client/surface.h>
27
28class ScreenEdgeHelper : public QObject
29{
30 Q_OBJECT
31protected:
32 ScreenEdgeHelper(QWidget *widget, QObject *parent = nullptr);
33
34 QWindow *window() const
35 {
36 return m_widget->windowHandle();
37 }
38
39 virtual void restore() = 0;
40
41public:
43
44 virtual void hide() = 0;
45 virtual void raiseOrShow(bool raise) = 0;
46 virtual void init(){};
47
48 virtual void moveToTop();
49 virtual void moveToRight();
50 virtual void moveToBottom();
51 virtual void moveToLeft();
52 virtual void moveToFloating();
53
55 {
56 hide();
57 m_timer->start(10000);
58 }
59
60private:
61 QWidget *m_widget;
62 QTimer *m_timer;
63};
64
66{
67 Q_OBJECT
68public:
69 ScreenEdgeHelperX11(QWidget *widget, QObject *parent = nullptr);
70 ~ScreenEdgeHelperX11() override = default;
71
72 void hide() override;
73 void raiseOrShow(bool raise) override;
74
75 void moveToTop() override;
76 void moveToRight() override;
77 void moveToBottom() override;
78 void moveToLeft() override;
79 void moveToFloating() override;
80
81protected:
82 void restore() override;
83
84private:
85 uint32_t m_locationValue = 2;
86 uint32_t m_actionValue = 0;
87 KWin::Xcb::Atom m_atom;
88};
89
91{
92 Q_OBJECT
93public:
94 ScreenEdgeHelperWayland(QWidget *widget, QObject *parent = nullptr);
95 ~ScreenEdgeHelperWayland() override = default;
96
97 void hide() override;
98 void raiseOrShow(bool raise) override;
99 void init() override;
100
101 bool eventFilter(QObject *watched, QEvent *event) override;
102
103protected:
104 void restore() override;
105
106private:
107 void setupSurface();
108 KWayland::Client::PlasmaShell *m_shell = nullptr;
109 KWayland::Client::PlasmaShellSurface *m_shellSurface = nullptr;
110 bool m_autoHide = true;
111};
112
113ScreenEdgeHelper::ScreenEdgeHelper(QWidget *widget, QObject *parent)
114 : QObject(parent)
115 , m_widget(widget)
116 , m_timer(new QTimer(this))
117{
118 m_timer->setSingleShot(true);
119 connect(m_timer, &QTimer::timeout, this, &ScreenEdgeHelper::restore);
120}
121
123
125{
126 const QRect geo = QGuiApplication::primaryScreen()->geometry();
127 m_widget->setGeometry(geo.x(), geo.y(), geo.width(), 100);
128}
129
131{
132 const QRect geo = QGuiApplication::primaryScreen()->geometry();
133 m_widget->setGeometry(geo.x(), geo.y(), geo.width(), 100);
134}
135
137{
138 const QRect geo = QGuiApplication::primaryScreen()->geometry();
139 m_widget->setGeometry(geo.x(), geo.y() + geo.height() - 100, geo.width(), 100);
140}
141
143{
144 const QRect geo = QGuiApplication::primaryScreen()->geometry();
145 m_widget->setGeometry(geo.x(), geo.y(), 100, geo.height());
146}
147
149{
150 const QRect geo = QGuiApplication::primaryScreen()->geometry();
151 m_widget->setGeometry(QRect(geo.center(), QSize(100, 100)));
152}
153
154ScreenEdgeHelperX11::ScreenEdgeHelperX11(QWidget *widget, QObject *parent)
155 : ScreenEdgeHelper(widget, parent)
156 , m_atom(QByteArrayLiteral("_KDE_NET_WM_SCREEN_EDGE_SHOW"))
157{
158}
159
161{
162 uint32_t value = m_locationValue | (m_actionValue << 8);
163 xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, window()->winId(), m_atom, XCB_ATOM_CARDINAL, 32, 1, &value);
164}
165
167{
168 xcb_delete_property(QX11Info::connection(), window()->winId(), m_atom);
169}
170
172{
173 m_actionValue = raise ? 1 : 0;
174}
175
177{
179 m_locationValue = 2;
180}
181
183{
185 m_locationValue = 4;
186}
187
189{
191 m_locationValue = 3;
192}
193
195{
197 m_locationValue = 1;
198}
199
201{
203 m_locationValue = 0;
204}
205
206using namespace KWayland::Client;
207
209 : ScreenEdgeHelper(widget, parent)
210{
211 ConnectionThread *connection = ConnectionThread::fromApplication(this);
212 Registry *registry = new Registry(connection);
213 registry->create(connection);
214
215 connect(registry, &Registry::interfacesAnnounced, this,
216 [registry, this] {
217 const auto interface = registry->interface(Registry::Interface::PlasmaShell);
218 if (interface.name == 0) {
219 return;
220 }
221 m_shell = registry->createPlasmaShell(interface.name, interface.version);
222 });
223
224 registry->setup();
225 connection->roundtrip();
226}
227
229{
230 window()->installEventFilter(this);
231 setupSurface();
232}
233
234void ScreenEdgeHelperWayland::setupSurface()
235{
236 if (!m_shell) {
237 return;
238 }
239 if (auto s = Surface::fromWindow(window())) {
240 m_shellSurface = m_shell->createSurface(s, window());
241 m_shellSurface->setRole(PlasmaShellSurface::Role::Panel);
242 m_shellSurface->setPanelBehavior(PlasmaShellSurface::PanelBehavior::AutoHide);
243 m_shellSurface->setPosition(window()->position());
244 }
245}
246
248{
249 if (m_shellSurface && m_autoHide) {
250 m_shellSurface->requestHideAutoHidingPanel();
251 }
252}
253
255{
256 if (m_shellSurface && m_autoHide) {
257 m_shellSurface->requestShowAutoHidingPanel();
258 }
259}
260
262{
263 m_autoHide = !raise;
264 if (m_shellSurface) {
265 if (raise) {
266 m_shellSurface->setPanelBehavior(PlasmaShellSurface::PanelBehavior::WindowsCanCover);
267 } else {
268 m_shellSurface->setPanelBehavior(PlasmaShellSurface::PanelBehavior::AutoHide);
269 }
270 }
271}
272
273bool ScreenEdgeHelperWayland::eventFilter(QObject *watched, QEvent *event)
274{
275 if (watched != window() || !m_shell) {
276 return false;
277 }
278 if (event->type() == QEvent::PlatformSurface) {
279 QPlatformSurfaceEvent *pe = static_cast<QPlatformSurfaceEvent *>(event);
280 if (pe->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
281 setupSurface();
282 } else {
283 delete m_shellSurface;
284 m_shellSurface = nullptr;
285 }
286 }
287 if (event->type() == QEvent::Move) {
288 if (m_shellSurface) {
289 m_shellSurface->setPosition(window()->position());
290 }
291 }
292 return false;
293}
294
295int main(int argc, char **argv)
296{
297 QApplication app(argc, argv);
298 QApplication::setApplicationDisplayName(QStringLiteral("Screen Edge Show Test App"));
299 ScreenEdgeHelper *helper = nullptr;
300 std::unique_ptr<QWidget> widget(new QWidget(nullptr, Qt::FramelessWindowHint));
301 if (KWindowSystem::isPlatformX11()) {
302 app.setProperty("x11Connection", QVariant::fromValue<void *>(QX11Info::connection()));
303 helper = new ScreenEdgeHelperX11(widget.get(), &app);
304 } else if (KWindowSystem::isPlatformWayland()) {
305 helper = new ScreenEdgeHelperWayland(widget.get(), &app);
306 }
307
308 if (!helper) {
309 return 2;
310 }
311
312 QPushButton *hideWindowButton = new QPushButton(QStringLiteral("Hide"), widget.get());
313
314 QObject::connect(hideWindowButton, &QPushButton::clicked, helper, &ScreenEdgeHelper::hide);
315
316 QPushButton *hideAndRestoreButton = new QPushButton(QStringLiteral("Hide and Restore after 10 sec"), widget.get());
317 QObject::connect(hideAndRestoreButton, &QPushButton::clicked, helper, &ScreenEdgeHelper::hideAndRestore);
318
319 QToolButton *edgeButton = new QToolButton(widget.get());
320
321 QCheckBox *raiseCheckBox = new QCheckBox("Raise:", widget.get());
322 QObject::connect(raiseCheckBox, &QCheckBox::toggled, helper, &ScreenEdgeHelper::raiseOrShow);
323
324 edgeButton->setText(QStringLiteral("Edge"));
325 edgeButton->setPopupMode(QToolButton::MenuButtonPopup);
326 QMenu *edgeButtonMenu = new QMenu(edgeButton);
327 QObject::connect(edgeButtonMenu->addAction("Top"), &QAction::triggered, helper, &ScreenEdgeHelper::moveToTop);
328 QObject::connect(edgeButtonMenu->addAction("Right"), &QAction::triggered, helper, &ScreenEdgeHelper::moveToRight);
329 QObject::connect(edgeButtonMenu->addAction("Bottom"), &QAction::triggered, helper, &ScreenEdgeHelper::moveToBottom);
330 QObject::connect(edgeButtonMenu->addAction("Left"), &QAction::triggered, helper, &ScreenEdgeHelper::moveToLeft);
331 edgeButtonMenu->addSeparator();
332 QObject::connect(edgeButtonMenu->addAction("Floating"), &QAction::triggered, helper, &ScreenEdgeHelper::moveToFloating);
333 edgeButton->setMenu(edgeButtonMenu);
334
335 QHBoxLayout *layout = new QHBoxLayout(widget.get());
336 layout->addWidget(hideWindowButton);
337 layout->addWidget(hideAndRestoreButton);
338 layout->addWidget(edgeButton);
339 widget->setLayout(layout);
340
341 const QRect geo = QGuiApplication::primaryScreen()->geometry();
342 widget->setGeometry(geo.x(), geo.y() + geo.height() - 100, geo.width(), 100);
343 widget->show();
344 helper->init();
345
346 return app.exec();
347}
348
349#include "screenedgeshowtest.moc"
virtual void moveToBottom()
QWindow * window() const
virtual void moveToFloating()
virtual void moveToLeft()
virtual void hide()=0
ScreenEdgeHelper(QWidget *widget, QObject *parent=nullptr)
virtual void restore()=0
virtual void moveToRight()
~ScreenEdgeHelper() override
virtual void raiseOrShow(bool raise)=0
ScreenEdgeHelperWayland(QWidget *widget, QObject *parent=nullptr)
bool eventFilter(QObject *watched, QEvent *event) override
~ScreenEdgeHelperWayland() override=default
void raiseOrShow(bool raise) override
~ScreenEdgeHelperX11() override=default
void moveToFloating() override
ScreenEdgeHelperX11(QWidget *widget, QObject *parent=nullptr)
void raiseOrShow(bool raise) override