KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
WindowBeingDragged.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019-2023 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 "WindowBeingDragged_p.h"
13#include "DragController_p.h"
14#include "Frame_p.h"
15#include "LayoutWidget_p.h"
16#include "Logging_p.h"
17#include "Utils_p.h"
18
19#ifdef KDDOCKWIDGETS_QTWIDGETS
20#include "widgets/TabBarWidget_p.h"
21#include "widgets/TabWidgetWidget_p.h"
22#endif
23
24#include <QPixmap>
25#include <QPainter>
26
27using namespace KDDockWidgets;
28
29static Draggable *bestDraggable(Draggable *draggable)
30{
31 if (!draggable)
32 return nullptr;
33
34 // When de detach a title bar it will get hidden and we only the title bar of the FloatingWindow is visible
36 // grabbing mouse on an hidden window works usually, it's some edge case on Windows with MFC.
37 if (auto titleBar = qobject_cast<TitleBar *>(draggable->asWidget())) {
38 if (titleBar->isVisible())
39 return draggable;
40
41 auto fw = qobject_cast<FloatingWindow *>(titleBar->window());
42 if (!fw) // defensive, doesn't happen
43 return draggable;
44
45 if (fw->titleBar() == titleBar) {
46 // Defensive, doesn't happen
47 return draggable;
48 } else {
49 if (KDDockWidgets::usesNativeTitleBar())
50 return fw;
51 return fw->titleBar();
52 }
53 } else {
54 return draggable;
55 }
56}
57
58WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw, Draggable *draggable)
59 : m_floatingWindow(fw)
60 , m_draggable(bestDraggable(draggable))
61 , m_draggableWidget(m_draggable ? m_draggable->asWidget() : nullptr)
62{
63 init();
64
65 if (!isWayland()) { // Wayland doesn't support setting opacity
66 // Set opacity while dragging, if needed
67 const qreal opacity = Config::self().draggedWindowOpacity();
68 if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
69 fw->setWindowOpacity(opacity);
70 }
71}
72
73WindowBeingDragged::WindowBeingDragged(Draggable *draggable)
74 : m_draggable(draggable)
75 , m_draggableWidget(m_draggable->asWidget())
76{
77 if (!isWayland()) {
78 qWarning() << Q_FUNC_INFO << "Wrong ctor called."; // Doesn't happen
79 Q_ASSERT(false);
80 return;
81 }
82}
83
84#ifdef DOCKS_DEVELOPER_MODE
85
86// Just used by tests
87WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw)
88 : m_floatingWindow(fw)
89 , m_draggable(nullptr)
90{
91}
92
93#endif
94
95WindowBeingDragged::~WindowBeingDragged()
96{
97 grabMouse(false);
98
99 if (!isWayland() && m_floatingWindow) { // Wayland doesn't support setting opacity
100 // Restore opacity to fully opaque if needed
101 const qreal opacity = Config::self().draggedWindowOpacity();
102 if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
103 m_floatingWindow->setWindowOpacity(1);
104 }
105}
106
107void WindowBeingDragged::init()
108{
109 Q_ASSERT(m_floatingWindow);
110 grabMouse(true);
111 m_floatingWindow->raise();
112}
113
114void WindowBeingDragged::grabMouse(bool grab)
115{
116 if (!m_draggableWidget)
117 return;
118
119 qCDebug(hovering) << "WindowBeingDragged: grab " << m_floatingWindow << grab << m_draggableWidget;
120 if (grab)
121 DragController::instance()->grabMouseFor(m_draggableWidget);
122 else
123 DragController::instance()->releaseMouse(m_draggableWidget);
124}
125
126QStringList WindowBeingDragged::affinities() const
127{
128 return m_floatingWindow ? m_floatingWindow->affinities()
129 : QStringList();
130}
131
132QSize WindowBeingDragged::size() const
133{
134 if (m_floatingWindow)
135 return m_floatingWindow->size();
136
137 return QSize();
138}
139
140QSize WindowBeingDragged::minSize() const
141{
142 if (m_floatingWindow)
143 return m_floatingWindow->layoutWidget()->layoutMinimumSize();
144
145 return {};
146}
147
148QSize WindowBeingDragged::maxSize() const
149{
150 if (m_floatingWindow)
151 return m_floatingWindow->layoutWidget()->layoutMaximumSizeHint();
152
153 return {};
154}
155
156bool WindowBeingDragged::contains(LayoutWidget *layoutWidget) const
157{
158 if (!layoutWidget)
159 return false;
160
161 if (m_floatingWindow)
162 return m_floatingWindow->layoutWidget() == layoutWidget;
163
164 if (auto fw = qobject_cast<FloatingWindow *>(m_draggableWidget->window())) {
165 // We're not dragging via the floating window itself, but via the tab bar. Still might represent floating window though.
166 return fw->layoutWidget() == layoutWidget && fw->hasSingleFrame();
167 }
168
169 return false;
170}
171
172QVector<DockWidgetBase *> WindowBeingDragged::dockWidgets() const
173{
174 if (m_floatingWindow)
175 return m_floatingWindow->dockWidgets();
176
177 return {};
178}
179
180Draggable *WindowBeingDragged::draggable() const
181{
182 return m_draggable;
183}
184
185WindowBeingDraggedWayland::WindowBeingDraggedWayland(Draggable *draggable)
186 : WindowBeingDragged(draggable)
187{
188 if (!isWayland()) {
189 // Doesn't happen
190 qWarning() << Q_FUNC_INFO << "This CTOR is only called on Wayland";
191 Q_ASSERT(false);
192 return;
193 }
194
195 if (auto tb = qobject_cast<TitleBar *>(draggable->asWidget())) {
196 if (auto fw = tb->floatingWindow()) {
197 // case #1: we're dragging the whole floating window by its titlebar
198 m_floatingWindow = fw;
199 } else if (Frame *frame = tb->frame()) {
200 m_frame = frame;
201 } else {
202 qWarning() << Q_FUNC_INFO << "Shouldn't happen. TitleBar of what ?";
203 }
204 } else if (auto fw = qobject_cast<FloatingWindow *>(draggable->asWidget())) {
205 // case #2: the floating window itself is the draggable, happens on platforms that support
206 // native dragging. Not the case for Wayland. But adding this case for completeness.
207 m_floatingWindow = fw;
208#ifdef KDDOCKWIDGETS_QTWIDGETS
209 } else if (auto tbw = qobject_cast<TabBarWidget *>(draggable->asWidget())) {
210 m_dockWidget = tbw->currentDockWidget();
211 } else if (auto tw = qobject_cast<TabWidgetWidget *>(draggable->asWidget())) {
212 m_frame = tw->frame();
213#endif
214 } else {
215 qWarning() << "Unknown draggable" << draggable->asWidget()
216 << "please fix";
217 }
218}
219
220WindowBeingDraggedWayland::~WindowBeingDraggedWayland()
221{
222}
223
224QPixmap WindowBeingDraggedWayland::pixmap() const
225{
226 QPixmap pixmap(size());
227 QPainter p(&pixmap);
228 p.setOpacity(0.7);
229
230 if (m_floatingWindow) {
231 m_floatingWindow->render(&p);
232 } else if (m_frame) {
233 m_frame->render(&p);
234 } else if (m_dockWidget) {
235 m_dockWidget->render(&p);
236 }
237
238 return pixmap;
239}
240
241QStringList WindowBeingDraggedWayland::affinities() const
242{
243 if (m_floatingWindow)
244 return WindowBeingDragged::affinities();
245 else if (m_frame)
246 return m_frame->affinities();
247 else if (m_dockWidget)
248 return { m_dockWidget->affinities() };
249
250 return {};
251}
252
253QVector<DockWidgetBase *> WindowBeingDraggedWayland::dockWidgets() const
254{
255 if (m_floatingWindow)
256 return WindowBeingDragged::dockWidgets();
257 else if (m_frame)
258 return m_frame->dockWidgets();
259 else if (m_dockWidget)
260 return { m_dockWidget };
261
262 return {};
263}
264
265QSize WindowBeingDraggedWayland::size() const
266{
267 if (m_floatingWindow)
268 return WindowBeingDragged::size();
269 else if (m_frame)
270 return m_frame->QWidgetAdapter::size();
271 else if (m_dockWidget)
272 return m_dockWidget->size();
273
274 qWarning() << Q_FUNC_INFO << "Unknown size, shouldn't happen";
275 return QSize();
276}
277
278QSize WindowBeingDraggedWayland::minSize() const
279{
280 if (m_floatingWindow) {
281 return WindowBeingDragged::minSize();
282 } else if (m_frame) {
283 return m_frame->minSize();
284 } else if (m_dockWidget) {
285 return Layouting::Widget::widgetMinSize(m_dockWidget.data());
286 }
287
288 qWarning() << Q_FUNC_INFO << "Unknown minSize, shouldn't happen";
289 return {};
290}
291
292QSize WindowBeingDraggedWayland::maxSize() const
293{
294 if (m_floatingWindow) {
295 return WindowBeingDragged::maxSize();
296 } else if (m_frame) {
297 return m_frame->maxSizeHint();
298 } else if (m_dockWidget) {
299 return Layouting::Widget::widgetMaxSize(m_dockWidget.data());
300 }
301
302 qWarning() << Q_FUNC_INFO << "Unknown maxSize, shouldn't happen";
303 return {};
304}
305
306bool WindowBeingDraggedWayland::isInWaylandDrag(Frame *frame) const
307{
308 return frame && m_frame == frame;
309}
static Draggable * bestDraggable(Draggable *draggable)
static Config & self()
returns the singleton Config instance
Definition Config.cpp:84
qreal draggedWindowOpacity() const
returns the opacity to use when dragging dock widgets By default it's 1.0, fully opaque
Definition Config.cpp:170
static QSize widgetMaxSize(const T *w)
Definition Widget.h:164
static QSize widgetMinSize(const T *w)
Definition Widget.h:152

© 2019-2023 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 on Wed Nov 1 2023 00:02:31 for KDDockWidgets API Documentation by doxygen 1.9.8