KDDockWidgets API Documentation 2.0
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->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
132 // Filter might have been deleted meanwhile
133 if (std::find(q->d->m_globalEventFilters.cbegin(), q->d->m_globalEventFilters.cend(),
134 filter)
135 == q->d->m_globalEventFilters.cend())
136 continue;
137
138 if (filter->onMouseEvent(view.get(), ev))
139 return true;
140
141 switch (ev->type()) {
143 if (filter->onMouseButtonPress(view.get(), ev))
144 return true;
145 break;
147 if (filter->onMouseButtonRelease(view.get(), ev))
148 return true;
149 break;
151 if (filter->onMouseButtonMove(view.get(), ev))
152 return true;
153 break;
155 if (filter->onMouseDoubleClick(view.get(), ev))
156 return true;
157 break;
158 default:
159 break;
160 }
161 }
162
163 return false;
164 }
165
166 ~GlobalEventFilter() override;
167 bool m_isProcessingAppQuitEvent = false;
168 Platform_qt *const q;
169};
170
171Platform_qt::GlobalEventFilter::~GlobalEventFilter() = default;
172
174 : m_globalEventFilter(new GlobalEventFilter(this))
175{
176 if (!qGuiApp)
177 qWarning() << "Please call KDDockWidgets::initPlatform() after QGuiApplication";
178}
179
180#ifdef DOCKS_DEVELOPER_MODE
181
182// ctor used by the tests only
184 : m_globalEventFilter(new GlobalEventFilter(this))
185{
186 // We want stability during tests.
187 // QMainWindow uses the factor for its margins, we don't want tests failing due
188 // to off by 1 or 2 pixels. Use 96dpi everywhere.
189 View_qt::s_logicalDpiFactorOverride = 1;
190}
191
192#endif
193
195{
196 delete m_globalEventFilter;
197}
198
199std::shared_ptr<View> Platform_qt::focusedView() const
200{
201 return qobjectAsView(qGuiApp->focusObject());
202}
203
204Core::Window::List Platform_qt::windows() const
205{
206 Core::Window::List windows;
207 const auto qtwindows = qGuiApp->topLevelWindows();
208 windows.reserve(qtwindows.size());
209 for (QWindow *qtwindow : qtwindows) {
210 windows << windowFromQWindow(qtwindow);
211 }
212
213 return windows;
214}
215
216std::shared_ptr<Core::Window> Platform_qt::qobjectAsWindow(QObject *obj) const
217{
218 if (auto window = qobject_cast<QWindow *>(obj))
219 return windowFromQWindow(window);
220 return nullptr;
221}
222
223int Platform_qt::screenNumberFor(std::shared_ptr<Core::Window> window) const
224{
225 if (!window)
226 return -1;
227
228 return screenNumberForQWindow(static_cast<Window *>(window.get())->qtWindow());
229}
230
232{
233 if (QScreen *screen = window->screen()) {
234 return qGuiApp->screens().indexOf(screen);
235 }
236
237 return -1;
238}
239
240void Platform_qt::sendEvent(View *view, QEvent *ev) const
241{
242 qGuiApp->sendEvent(QtCommon::View_qt::asQObject(view), ev);
243}
244
246{
247 return m_globalEventFilter->m_isProcessingAppQuitEvent;
248}
249
251{
252 return qGuiApp->applicationName();
253}
254
255void Platform_qt::setMouseCursor(Qt::CursorShape shape, bool discardLast)
256{
257 if (discardLast) {
258 qGuiApp->changeOverrideCursor(shape);
259 } else {
260 qGuiApp->setOverrideCursor(shape);
261 }
262}
263
265{
266 qGuiApp->restoreOverrideCursor();
267}
268
270{
271 return QCursor::pos();
272}
273
278
280{
281 if (qGuiApp->platformName() == QLatin1String("wayland"))
283
284 if (qGuiApp->platformName() == QLatin1String("offscreen"))
286
287 if (qGuiApp->platformName() == QLatin1String("xcb"))
288 return DisplayType::X11;
289
290 if (qGuiApp->platformName() == QLatin1String("eglfs"))
292
293 return DisplayType::Other;
294}
295
297{
298 return qGuiApp->mouseButtons() & Qt::LeftButton;
299}
300
301/*static*/
303{
304 return static_cast<Platform_qt *>(Platform::instance());
305}
306
307Screen::List Platform_qt::screens() const
308{
309 const auto qscreens = qGuiApp->screens();
310 Screen::List screens;
311 screens.reserve(qscreens.size());
312 for (auto qscreen : qscreens) {
313 screens.push_back(std::make_shared<Screen_qt>(qscreen));
314 }
315 return screens;
316}
317
318Screen::Ptr Platform_qt::primaryScreen() const
319{
320 return std::make_shared<Screen_qt>(qGuiApp->primaryScreen());
321}
322
323void Platform_qt::runDelayed(int ms, Core::DelayedCall *c)
324{
325 QTimer::singleShot(ms, qGuiApp, [c] { c->call(); delete c; });
326}
327
328QByteArray Platform_qt::readFile(const QString &fileName, bool &ok) const
329{
330 QFile f(fileName);
332 if (!ok) {
333 KDDW_ERROR("Failed to open {}, error={}", fileName, f.errorString());
334 return {};
335 }
336
337 return f.readAll();
338}
339
341{
342#if defined(Q_OS_WIN)
343 // Aero-snap requires Windows 10
345#endif
346 return false;
347}
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...
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
int screenNumberFor(std::shared_ptr< Core::Window >) 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