KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
qtquick/views/FloatingWindow.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 "FloatingWindow.h"
13#include "Config.h"
14#include "qtquick/ViewFactory.h"
15
16#include "TitleBar.h"
17
18#include "core/Logging_p.h"
19#include "core/Utils_p.h"
20#include "core/View_p.h"
21#include "core/FloatingWindow_p.h"
22#include "core/layouting/Item_p.h"
23
24#include "kddockwidgets/core/DropArea.h"
25#include "kddockwidgets/core/FloatingWindow.h"
26#include "kddockwidgets/core/MainWindow.h"
27#include "kddockwidgets/core/TitleBar.h"
28
29#include "core/WidgetResizeHandler_p.h"
30#include "qtquick/Platform.h"
31#include "qtquick/Window_p.h"
35
36#include <QQuickView>
37#include <QDebug>
38
39using namespace KDDockWidgets;
40using namespace KDDockWidgets::QtQuick;
41
42namespace KDDockWidgets {
43
44class QuickView : public QQuickView
45{
46 Q_OBJECT
47public:
48 explicit QuickView(QQmlEngine *qmlEngine, FloatingWindow *view)
49 : QQuickView(qmlEngine, nullptr)
50 , m_view(view)
51 {
53 setColor(QColor(Qt::transparent));
54
55 updateSize();
56
57 auto item = asQQuickItem(view);
58 connect(item, &QQuickItem::widthChanged, this, &QuickView::onRootItemWidthChanged);
59 connect(item, &QQuickItem::heightChanged, this, &QuickView::onRootItemHeightChanged);
60 }
61
62 ~QuickView() override;
63
64 bool event(QEvent *ev) override
65 {
66 if (ev->type() == QEvent::FocusAboutToChange) {
67 // qquickwindow.cpp::event(FocusAboutToChange) removes the item grabber. Inibit that
68 return true;
69 } else if (ev->type() == QEvent::Resize) {
70 updateRootItemSize();
71 } else if (isNonClientMouseEvent(ev) || ev->type() == QEvent::Move) {
72 // Mimic QWidget behaviour: The non-client mouse events go to the QWidget not the
73 // QWindow. In our case the QQuickItem. I mean, they also go to QWindow, but for our
74 // QtWidgets impl we process them at the QWidget level, so use the same approach so we
75 // maintain a single code path for processing mouse events
77 return true;
78 }
79
80 if (ev->type() == QEvent::Expose) {
81 Core::AtomicSanityChecks checks(m_view->rootItem());
82 auto res = QQuickView::event(ev);
83 return res;
84 } else {
85 return QQuickView::event(ev);
86 }
87 }
88
89 void onRootItemWidthChanged()
90 {
91 setWidth(int(m_view->width()));
92 }
93
94 void onRootItemHeightChanged()
95 {
96 setHeight(int(m_view->height()));
97 }
98
99 void updateSize()
100 {
101 resize(m_view->Core::View::size());
102 }
103
104 void updateRootItemSize()
105 {
106 if (m_view->asFloatingWindowController()->beingDeleted())
107 return;
108
109 Core::AtomicSanityChecks checks(m_view->rootItem());
110 m_view->Core::View::setSize(size());
111 }
112
113#ifdef KDDW_FRONTEND_QT_WINDOWS
114 bool nativeEvent(const QByteArray &eventType, void *message,
115 Qt5Qt6Compat::qintptr *result) override
116 {
117 // To enable aero snap we need to tell Windows where's our custom title bar
118 Core::FloatingWindow *fw = m_view->asFloatingWindowController();
119 if (!fw->beingDeleted()
120 && WidgetResizeHandler::handleWindowsNativeEvent(fw, eventType, message, result))
121 return true;
122
123 return QWindow::nativeEvent(eventType, message, result);
124 }
125#endif
126private:
127 FloatingWindow *const m_view;
128};
129
130QuickView::~QuickView() = default;
131
132}
133
134
136 QtQuick::MainWindow *parent,
137 Qt::WindowFlags flags)
138 : QtQuick::View(controller, Core::ViewType::FloatingWindow, parent, flags)
139 , m_quickWindow(new QuickView(plat()->qmlEngine(), this))
140 , m_controller(controller)
141{
142 connect(m_quickWindow, &QWindow::windowStateChanged, this, &FloatingWindow::onWindowStateChanged);
143}
144
146{
147 m_inDtor = true;
148 setParent(static_cast<Core::View *>(nullptr));
149 if (qobject_cast<QQuickView *>(m_quickWindow)) // QObject cast just to make sure the QWindow is
150 // not in ~QObject already
151 delete m_quickWindow;
152}
153
155{
156 // Doesn't matter if it's not visible. We don't want the min-size to jump around. Also not so
157 // easy to track as we don't have layouts
158 const int margins = contentsMargins();
159 return m_controller->multiSplitter()->view()->minSize() + QSize(0, titleBarHeight())
160 + QSize(margins * 2, margins * 2);
161}
162
164{
165 // Not needed with QtWidgets, but needed with QtQuick as we don't have layouts
166 geo.setSize(geo.size().expandedTo(minSize()));
167
168 parentItem()->setSize(geo.size());
169 m_quickWindow->setGeometry(geo);
170}
171
172int FloatingWindow::contentsMargins() const
173{
174 return m_visualItem->property("margins").toInt();
175}
176
177int FloatingWindow::titleBarHeight() const
178{
179 return m_visualItem->property("titleBarHeight").toInt();
180}
181
182QWindow *FloatingWindow::candidateParentWindow() const
183{
184 if (auto mainWindow = qobject_cast<MainWindow *>(QObject::parent())) {
185 return mainWindow->QQuickItem::window();
186 }
187
188 return nullptr;
189}
190
191void FloatingWindow::init()
192{
193 if (QWindow *transientParent = candidateParentWindow()) {
194 m_quickWindow->setTransientParent(candidateParentWindow());
195 // This mimics the QWidget behaviour, where we not only have a transient parent but also
196 // a parent for cleanup. Calling QWindow::setParent() here would clip it to the parent
197 m_quickWindow->QObject::setParent(transientParent);
198 m_quickWindow->setObjectName(QStringLiteral("Floating QWindow with parent")); // for debug
199 } else {
200 m_quickWindow->setObjectName(QStringLiteral("Floating QWindow"));
201 }
202
203 setParent(m_quickWindow->contentItem());
204 WidgetResizeHandler::setupWindow(Core::Window::Ptr(new QtQuick::Window(m_quickWindow)));
205 m_quickWindow->installEventFilter(this); // for window resizing
206 m_controller->maybeCreateResizeHandler();
207
208 m_visualItem = createItem(m_quickWindow->engine(),
209 plat()->viewFactory()->floatingWindowFilename().toString());
210 Q_ASSERT(m_visualItem);
211
212 // Ensure our window size is never smaller than our min-size
214
215 m_visualItem->setParent(this);
216 m_visualItem->setParentItem(this);
217
218 m_quickWindow->setFlags(flags());
219
220 m_controller->updateTitleAndIcon();
221
222#ifdef KDDW_FRONTEND_QT_WINDOWS
223 // Workaround for QTBUG-120269 , no alt-tab thumbail if starting minimized.
224 // Do a nice workaround of rendering transparently then minimizing that
226 m_quickWindow->setOpacity(0.0);
227 auto guard = new QObject(this);
228 connect(m_quickWindow, &QQuickView::frameSwapped, guard, [this, guard] {
229 if (m_controller->dptr()->m_minimizationPending) {
230 delete guard;
231 m_controller->dptr()->m_minimizationPending = false;
232 showMinimized();
233 m_quickWindow->setOpacity(1);
234 }
235 });
236 }
237#endif
238
239 m_quickWindow->show();
240
241 connect(this, &QQuickItem::visibleChanged, this, [this] {
242 if (!isVisible() && !Core::View::d->aboutToBeDestroyed())
243 m_controller->scheduleDeleteLater();
244 });
245}
246
248{
249 if (auto tb = m_controller->titleBar())
250 return qobject_cast<TitleBar *>(asQQuickItem(tb->view()));
251
252 return nullptr;
253}
254
256{
257 if (auto da = m_controller->dropArea())
258 return qobject_cast<DropArea *>(asQQuickItem(da->view()));
259
260 return nullptr;
261}
262
263Core::Item *FloatingWindow::rootItem() const
264{
265 if (auto da = m_controller->dropArea())
266 return da->rootItem();
267 return nullptr;
268}
269
270void FloatingWindow::onWindowStateChanged(Qt::WindowState state)
271{
272 const auto newState = WindowState(state);
273 m_controller->setLastWindowManagerState(newState);
274 m_controller->dptr()->windowStateChanged.emit();
275#if defined(Q_OS_WIN)
276 if (window()->hasBeenMinimizedDirectlyFromRestore() && newState != WindowState::Minimized) {
277 window()->setHasBeenMinimizedDirectlyFromRestore(false);
278 // restore our nice frames
279 WidgetResizeHandler::requestNCCALCSIZE(HWND(window()->handle()));
280 }
281#endif
282}
283
284#include "FloatingWindow.moc"
Application-wide config to tune certain behaviours of the framework.
@ InternalFlag_UseTransparentFloatingWindow
Definition Config.h:164
static Config & self()
returns the singleton Config instance
Definition Config.cpp:88
View * view() const
Returns the view associated with this controller, if any.
Core::DropArea * multiSplitter() const
Returns the MultiSplitter.
FloatingWindowFlags floatingWindowFlags() const
Returns the per-floating window flags.
bool beingDeleted() const
Returns whether a deleteLater has already been issued.
void updateTitleAndIcon()
updates the title and the icon
void scheduleDeleteLater()
Equivalent to deleteLater() but sets beingDeleted() to true.
Core::TitleBar * titleBar() const
Returns the title bar.
static Platform * instance()
Returns the platform singleton.
virtual void sendEvent(View *, Event *) const =0
Sends the specified event to the specified view.
virtual void setSize(int width, int height)=0
virtual Size minSize() const =0
Core::HANDLE handle() const override
Returns a handle for the GUI element This value only makes sense to the frontend. For example,...
FloatingWindow(Core::FloatingWindow *controller, QtQuick::MainWindow *parent=nullptr, Qt::WindowFlags flags={})
A docking area for dock widgets Named MainWindow as it's the QtWidgets/QMainWindow counterpart....
Qt::WindowFlags flags() const override
static QQuickItem * createItem(QQmlEngine *engine, const QString &filename, QQmlContext *context=nullptr)
Convenience to create a QQuickItem.
void setParent(Core::View *parent) override
std::shared_ptr< Core::Window > window() const override
Returns the window this view is inside For the Qt frontend, this wraps a QWindow. Like QWidget::windo...
QQuickItem * asQQuickItem(Core::View *view)
Class to abstract QAction, so code still works with QtQuick and Flutter.
QtQuick::Platform * plat()
void connect(T &&future, QObjectSubclass *context, Callback func)
Definition qcorotask.h:721
FocusAboutToChange
QEvent::Type type() const const
QObject * parent() const const
void setSize(const QSize &size)
QSize size() const const
QSize expandedTo(const QSize &otherSize) const const
transparent
WindowState
typedef WindowFlags
A factory class for allowing the user to customize some internal widgets.
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result)
void windowStateChanged(Qt::WindowState windowState)

© 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