KDDockWidgets API Documentation 2.0
Loading...
Searching...
No Matches
qtwidgets/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 "core/FloatingWindow_p.h"
14#include "kddockwidgets/core/FloatingWindow.h"
15#include "kddockwidgets/core/Group.h"
16#include "kddockwidgets/core/TitleBar.h"
17#include "kddockwidgets/core/MainWindow.h"
18#include "kddockwidgets/core/DropArea.h"
19
20#include "core/Logging_p.h"
21#include "core/Utils_p.h"
22#include "core/View_p.h"
23#include "core/DragController_p.h"
24#include "core/WidgetResizeHandler_p.h"
25#include "core/DockRegistry_p.h"
26
27#include "TitleBar.h"
28
29#include <QApplication>
30#include <QMainWindow>
31#include <QPainter>
32#include <QVBoxLayout>
33#include <QWindow>
34#include <QWindowStateChangeEvent>
35
36#ifdef Q_OS_WIN
37#include <Windows.h>
38#endif
39
40using namespace KDDockWidgets;
41using namespace KDDockWidgets::QtWidgets;
42
43class FloatingWindow::Private
44{
45public:
47 : m_vlayout(new QVBoxLayout(q))
48 , m_controller(controller)
49 {
50 }
51
52 QVBoxLayout *const m_vlayout;
53 Core::FloatingWindow *const m_controller;
54 bool m_connectedToScreenChanged = false;
55 KDBindings::ScopedConnection m_numGroupsChangedConnection;
56 KDBindings::ScopedConnection m_screenChangedConnection;
57};
58
60 QMainWindow *parent, Qt::WindowFlags windowFlags)
61 : View<QWidget>(controller, Core::ViewType::FloatingWindow, parent, windowFlags)
62 , d(new Private(this, controller))
63{
64}
65
67{
68 delete d;
69}
70
72{
73 if (Config::self().disabledPaintEvents() & Config::CustomizableWidget_FloatingWindow) {
75 return;
76 }
77
78 QPainter p(this);
79 QPen pen(0x666666);
80 pen.setWidth(1);
82 p.setPen(pen);
83 const qreal halfPenWidth = p.pen().widthF() / 2;
84 const QRectF rectf = rect();
85 p.drawRect(rectf.adjusted(halfPenWidth, halfPenWidth, -halfPenWidth, -halfPenWidth));
86}
87
89{
92 if ((windowFlags() & Qt::Tool) == Qt::Tool) {
94 // Let's refuse to maximize Qt::Tool. It's not natural.
95 // Just avoid this combination: Flag_NativeTitleBar + Qt::Tool +
96 // Flag_DoubleClickMaximizes
97 } else {
98 // Double clicking a Qt::Tool title-bar. Triggers a redocking.
99 if (d->m_controller->titleBar()->isFloating()) { // redocking nested floating
100 // windows aren't supported
101 d->m_controller->titleBar()->onFloatClicked();
102 return true;
103 }
104 }
105 } else {
106 // A normal Qt::Window window. The OS handles the double click.
107 // In general this will maximize the window, that's the native behaviour.
108 }
109 } else if (ev->type() == QEvent::Show && !d->m_connectedToScreenChanged) {
110 // We connect after QEvent::Show, so we have a QWindow. Qt doesn't offer much API to
111 // intercept screen events
112 d->m_connectedToScreenChanged = true;
113 window()->onScreenChanged(this, [](QObject *, auto window) {
114 DockRegistry::self()->dptr()->windowChangedScreen.emit(window);
115 });
116
118 } else if (ev->type() == QEvent::ActivationChange) {
119 // Since QWidget is missing a signal for window activation
120 d->m_controller->dptr()->activatedChanged.emit();
121 } else if (ev->type() == QEvent::StatusTip && QWidget::parent()) {
122 // show status tips in the main window
123 return QWidget::parent()->event(ev);
124 }
125
126 return View<QWidget>::event(ev);
127}
128
130{
131 d->m_numGroupsChangedConnection = d->m_controller->dptr()->numGroupsChanged.connect([this] {
133 });
134
135 d->m_vlayout->setSpacing(0);
136 updateMargins();
137 d->m_vlayout->addWidget(View_qt::asQWidget(d->m_controller->titleBar()));
138 d->m_vlayout->addWidget(View_qt::asQWidget(d->m_controller->dropArea()));
139
140 d->m_screenChangedConnection = DockRegistry::self()->dptr()->windowChangedScreen.connect([this](Core::Window::Ptr w) {
141 if (View::d->isInWindow(w))
142 updateMargins();
143 });
144}
145
146void FloatingWindow::updateMargins()
147{
148 d->m_vlayout->setContentsMargins(QMargins(4, 4, 4, 4) * logicalDpiFactor(this));
149}
150
152{
153 return d->m_controller;
154}
155
157{
158 if (ev->type() == QEvent::WindowStateChange) {
159 // QWidget::windowState() is not reliable as it's emitted both for the spontaneous (async)
160 // event and non-spontaneous (sync) The sync one being useless, as the window manager can
161 // still have the old state. Only emit windowStateChanged once the window manager tells us
162 // the state has actually changed See also QTBUG-102430
163 if (ev->spontaneous()) {
164 const auto newState = WindowState(windowHandle()->windowState());
165 d->m_controller->setLastWindowManagerState(newState);
166 d->m_controller->dptr()->windowStateChanged.emit();
167#if defined(Q_OS_WIN)
168 if (window()->hasBeenMinimizedDirectlyFromRestore() && newState != WindowState::Minimized) {
169 window()->setHasBeenMinimizedDirectlyFromRestore(false);
170 // restore our nice frames
171 WidgetResizeHandler::requestNCCALCSIZE(HWND(window()->handle()));
172 }
173#endif
174 }
175 }
176
178}
179
180#if defined(Q_OS_WIN)
181bool FloatingWindow::nativeEvent(const QByteArray &eventType, void *message,
182 Qt5Qt6Compat::qintptr *result)
183{
184 auto fw = floatingWindow();
185 if (fw->beingDeleted())
186 return QWidget::nativeEvent(eventType, message, result);
187
188 if (KDDockWidgets::usesAeroSnapWithCustomDecos()) {
189 // To enable aero snap we need to tell Windows where's our custom title bar
190 if (WidgetResizeHandler::handleWindowsNativeEvent(fw, eventType, message, result))
191 return true;
192 } else if (KDDockWidgets::usesNativeTitleBar()) {
193 auto msg = static_cast<MSG *>(message);
194 if (msg->message == WM_SIZING) {
195 // Cancel any drag if we're resizing
196 Core::DragController::instance()->dragCanceled.emit();
197 }
198 }
199
200 return QWidget::nativeEvent(eventType, message, result);
201}
202#endif
A ScopedConnection is a RAII-style way to make sure a Connection is disconnected.
Definition signal.h:533
@ CustomizableWidget_FloatingWindow
Definition Config.h:146
static Config & self()
returns the singleton Config instance
Definition Config.cpp:88
Flags flags() const
returns the chosen flags
Definition Config.cpp:102
Controller * controller() const
Returns this view's controller.
static DockRegistry * self()
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, QMainWindow *parent=nullptr, Qt::WindowFlags windowFlags={})
std::shared_ptr< Core::Window > window() const override
qreal logicalDpiFactor(const QWidget *w)
Class to abstract QAction, so code still works with QtQuick and Flutter.
NonClientAreaMouseButtonDblClick
bool spontaneous() const const
QEvent::Type type() const const
Q_EMITQ_EMIT
virtual bool event(QEvent *e)
void installEventFilter(QObject *filterObj)
QObject * parent() const const
void drawRect(const QRectF &rectangle)
const QPen & pen() const const
void setPen(const QColor &color)
void setJoinStyle(Qt::PenJoinStyle style)
void setWidth(int width)
qreal widthF() const const
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
MiterJoin
typedef WindowFlags
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result)
virtual void paintEvent(QPaintEvent *event)
QWindow * windowHandle() const const
Qt::WindowStates windowState() 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