KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
qtcommon/Platform.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
12#include "Platform.h"
13#include "Window_p.h"
14#include "kddockwidgets/KDDockWidgets.h"
15#include "kddockwidgets/core/EventFilterInterface.h"
16#include "core/Platform_p.h"
17#include "core/Utils_p.h"
18#include "core/Logging_p.h"
19#include "core/DelayedCall_p.h"
20#include "qtcommon/View.h"
21
22#include <QWindow>
23#include <QDebug>
24#include <QGuiApplication>
25#include <QElapsedTimer>
26#include <QScreen>
27#include <QTimer>
28#include <QFile>
29#include <QOperatingSystemVersion>
30
31using namespace KDDockWidgets;
32using namespace KDDockWidgets::QtCommon;
33using namespace KDDockWidgets::Core;
34
35// clazy:excludeall=missing-qobject-macro
36
37class Platform_qt::GlobalEventFilter : public QObject
38{
39public:
40 explicit GlobalEventFilter(Platform_qt *qq)
41 : q(qq)
42 {
43 if (qGuiApp) {
44 qGuiApp->installEventFilter(this);
45 } else {
46 qWarning() << Q_FUNC_INFO << "Expected a qGuiApp!";
47 }
48 }
49
50 bool eventFilter(QObject *o, QEvent *ev) override
51 {
52 if (ev->type() == QEvent::Expose)
53 return handleExpose(o);
54 else if (QMouseEvent *me = mouseEvent(ev))
55 return handleMouseEvent(o, me);
56 else if (isDnDEvent(ev))
57 return handleDnDEvent(o, ev);
58 else if (ev->type() == QEvent::Move)
59 return handleMoveEvent(o, ev);
60 else if (ev->type() != QEvent::Quit || m_isProcessingAppQuitEvent)
61 return false;
62
63 auto view = Platform_qt::instance()->qobjectAsView(o);
64 if (!view)
65 return false;
66
67 m_isProcessingAppQuitEvent = true;
68 qGuiApp->sendEvent(qApp, ev);
69 m_isProcessingAppQuitEvent = false;
70 return true;
71 }
72
73 bool handleMoveEvent(QObject *o, QEvent *)
74 {
75 if (q->d->m_globalEventFilters.empty())
76 return false;
77
78 auto view = Platform_qt::instance()->qobjectAsView(o);
79 for (EventFilterInterface *filter : std::as_const(q->d->m_globalEventFilters)) {
80 if (filter->onMoveEvent(view.get()))
81 return true;
82 }
83
84 return false;
85 }
86
87 bool handleDnDEvent(QObject *o, QEvent *ev)
88 {
89 if (q->d->m_globalEventFilters.empty())
90 return false;
91
92 if (auto view = Platform_qt::instance()->qobjectAsView(o)) {
93 for (EventFilterInterface *filter : std::as_const(q->d->m_globalEventFilters)) {
94 if (filter->onDnDEvent(view.get(), ev))
95 return true;
96 }
97 }
98
99 return false;
100 }
101
102 bool handleExpose(QObject *o)
103 {
104 if (q->d->m_globalEventFilters.empty())
105 return false;
106
107 auto window = Platform_qt::instance()->qobjectAsWindow(o);
108 if (!window)
109 return false;
110
111 for (EventFilterInterface *filter : std::as_const(q->d->m_globalEventFilters)) {
112 if (filter->enabled() && filter->onExposeEvent(window))
113 return true;
114 }
115
116 return false;
117 }
118
119 bool handleMouseEvent(QObject *watched, QMouseEvent *ev)
120 {
121 if (q->d->m_globalEventFilters.empty())
122 return false;
123
124 auto view = Platform_qt::instance()->qobjectAsView(watched);
125
126 // Make a copy, as there could be reentrancy and filters getting removed while event being
127 // processed
128 const auto &filters = std::as_const(q->d->m_globalEventFilters);
129
130 for (EventFilterInterface *filter : filters) {
131 // Filter might have been deleted meanwhile
132 if (std::find(q->d->m_globalEventFilters.cbegin(), q->d->m_globalEventFilters.cend(),
133 filter)
134 == q->d->m_globalEventFilters.cend())
135 continue;
136
137 if (!filter->enabled())
138 continue;
139
140 if (filter->onMouseEvent(view.get(), ev))
141 return true;
142
143 switch (ev->type()) {
145 if (filter->onMouseButtonPress(view.get(), ev))
146 return true;
147 break;
149 if (filter->onMouseButtonRelease(view.get(), ev))
150 return true;
151 break;
153 if (filter->onMouseButtonMove(view.get(), ev))
154 return true;
155 break;
157 if (filter->onMouseDoubleClick(view.get(), ev))
158 return true;
159 break;
160 default:
161 break;
162 }
163 }
164
165 return false;
166 }
167
168 ~GlobalEventFilter() override;
169 bool m_isProcessingAppQuitEvent = false;
170 Platform_qt *const q;
171};
172
173Platform_qt::GlobalEventFilter::~GlobalEventFilter() = default;
174
176 : m_globalEventFilter(new GlobalEventFilter(this))
177{
178 if (!qGuiApp)
179 qWarning() << "Please call KDDockWidgets::initPlatform() after QGuiApplication";
180}
181
182#ifdef DOCKS_DEVELOPER_MODE
183
184// ctor used by the tests only
186 : m_globalEventFilter(new GlobalEventFilter(this))
187{
188 // We want stability during tests.
189 // QMainWindow uses the factor for its margins, we don't want tests failing due
190 // to off by 1 or 2 pixels. Use 96dpi everywhere.
191 View_qt::s_logicalDpiFactorOverride = 1;
192}
193
194#endif
195
197{
198 delete m_globalEventFilter;
199}
200
201std::shared_ptr<View> Platform_qt::focusedView() const
202{
203 return qobjectAsView(qGuiApp->focusObject());
204}
205
206Core::Window::List Platform_qt::windows() const
207{
208 Core::Window::List windows;
209 const auto qtwindows = qGuiApp->topLevelWindows();
210 windows.reserve(qtwindows.size());
211 for (QWindow *qtwindow : qtwindows) {
212 windows << windowFromQWindow(qtwindow);
213 }
214
215 return windows;
216}
217
218std::shared_ptr<Core::Window> Platform_qt::qobjectAsWindow(QObject *obj) const
219{
220 if (auto window = qobject_cast<QWindow *>(obj))
221 return windowFromQWindow(window);
222 return nullptr;
223}
224
225int Platform_qt::screenNumberForWindow(std::shared_ptr<Core::Window> window) const
226{
227 if (!window)
228 return -1;
229
230 return screenNumberForQWindow(static_cast<Window *>(window.get())->qtWindow());
231}
232
234{
235 if (QScreen *screen = window->screen()) {
236 return qGuiApp->screens().indexOf(screen);
237 }
238
239 return -1;
240}
241
242void Platform_qt::sendEvent(View *view, QEvent *ev) const
243{
244 qGuiApp->sendEvent(QtCommon::View_qt::asQObject(view), ev);
245}
246
248{
249 return m_globalEventFilter->m_isProcessingAppQuitEvent;
250}
251
253{
254 return qGuiApp->applicationName();
255}
256
257void Platform_qt::setMouseCursor(Qt::CursorShape shape, bool discardLast)
258{
259 if (discardLast) {
260 qGuiApp->changeOverrideCursor(shape);
261 } else {
262 qGuiApp->setOverrideCursor(shape);
263 }
264}
265
267{
268 qGuiApp->restoreOverrideCursor();
269}
270
272{
273 return QCursor::pos();
274}
275
280
282{
283 if (qGuiApp->platformName() == QLatin1String("wayland"))
285
286 if (qGuiApp->platformName() == QLatin1String("offscreen"))
288
289 if (qGuiApp->platformName() == QLatin1String("xcb"))
290 return DisplayType::X11;
291
292 if (qGuiApp->platformName() == QLatin1String("eglfs"))
294
295 if (qGuiApp->platformName() == QLatin1String("windows"))
297
298 return DisplayType::Other;
299}
300
302{
303 return qGuiApp->mouseButtons() & Qt::LeftButton;
304}
305
306/*static*/
308{
309 return static_cast<Platform_qt *>(Platform::instance());
310}
311
312Screen::List Platform_qt::screens() const
313{
314 const auto qscreens = qGuiApp->screens();
315 Screen::List screens;
316 screens.reserve(qscreens.size());
317 for (auto qscreen : qscreens) {
318 screens.push_back(std::make_shared<Screen_qt>(qscreen));
319 }
320 return screens;
321}
322
323Screen::Ptr Platform_qt::primaryScreen() const
324{
325 return std::make_shared<Screen_qt>(qGuiApp->primaryScreen());
326}
327
328void Platform_qt::runDelayed(int ms, Core::DelayedCall *c)
329{
330 QTimer::singleShot(ms, qGuiApp, [c] { c->call(); delete c; });
331}
332
333QByteArray Platform_qt::readFile(const QString &fileName, bool &ok) const
334{
335 QFile f(fileName);
337 if (!ok) {
338 KDDW_ERROR("Failed to open {}, error={}", fileName, f.errorString());
339 return {};
340 }
341
342 return f.readAll();
343}
344
346{
347#if defined(Q_OS_WIN)
348 // Aero-snap requires Windows 10
350#endif
351 return false;
352}
DisplayType
Enum describing the graphics stack type.
static Platform * instance()
Returns the platform singleton.
Baseclass platform for Qt based platform Useful since QtWidgets and QtQuick share some similarities.
QString applicationName() const override
Returns the application name This name will be used as title of floating dock widgets which contain m...
int screenNumberForWindow(std::shared_ptr< Core::Window >) const override
bool isProcessingAppQuitEvent() const override
Returns whether we're processing a Event::Quit.
QVector< std::shared_ptr< Core::Screen > > screens() const override
Returns all available screens.
void runDelayed(int ms, Core::DelayedCall *) override
virtual std::shared_ptr< Core::View > qobjectAsView(QObject *) const =0
Returns the specified QObject casted to View Nullptr if it's not a view.
void restoreMouseCursor() override
Undoes the call to setMouseCursor()
QByteArray readFile(const QString &fileName, bool &ok) const override
void sendEvent(Core::View *, QEvent *) const override
void setMouseCursor(Qt::CursorShape, bool discardLast=false) override
Sets the mouse cursor to the specified shape, this has an application-wide effect Call restoreMouseCu...
bool isLeftMouseButtonPressed() const override
Returns whether the left mouse button is pressed.
virtual std::shared_ptr< Core::Window > windowFromQWindow(QWindow *) const =0
std::shared_ptr< Core::Screen > primaryScreen() const override
std::shared_ptr< Core::Window > qobjectAsWindow(QObject *) const
bool supportsAeroSnap() const override
Only supported on Qt, for windows.
QVector< std::shared_ptr< Core::Window > > windows() const override
Returns all windows.
QPoint cursorPos() const override
Returns the mouse cursor position in screen coordinates.
DisplayType displayType() const override
Returns the type of graphics stack being used.
std::shared_ptr< Core::View > focusedView() const override
Returns the focused view, if any.
static QObject * asQObject(View *)
Class to abstract QAction, so code still works with QtQuick and Flutter.
Definition utils.h:161
QPoint pos()
void setPos(int x, int y)
QEvent::Type type() const const
virtual bool open(QIODevice::OpenMode mode) override
QString errorString() const const
QByteArray readAll()
virtual bool eventFilter(QObject *watched, QEvent *event)
QOperatingSystemVersion current()
int majorVersion() const const
CursorShape
LeftButton
QScreen * screen() const const

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8