KDDockWidgets API Documentation 2.1
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 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 "kddockwidgets/KDDockWidgets.h"
14#include "DragController_p.h"
15#include "Logging_p.h"
16#include "Utils_p.h"
17
18#include "core/DockWidget_p.h"
19#include "kddockwidgets/core/TitleBar.h"
20#include "kddockwidgets/core/Stack.h"
21#include "kddockwidgets/core/Group.h"
22#include "kddockwidgets/core/Platform.h"
23#include "kddockwidgets/core/Layout.h"
24#include "kddockwidgets/core/FloatingWindow.h"
25
26#include <cmath>
27
28#ifdef KDDW_FRONTEND_QT
29#include <QPainter>
30#endif
31
32using namespace KDDockWidgets;
33using namespace KDDockWidgets::Core;
34
35static Draggable *bestDraggable(Draggable *draggable)
36{
37 if (!draggable)
38 return nullptr;
39
40 // When de detach a title bar it will get hidden and we only the title bar of the FloatingWindow
41 // is visible
43 // grabbing mouse on an hidden window works usually, it's some edge case on Windows with MFC.
44 if (auto titleBar = draggable->asView()->asTitleBarController()) {
45 if (titleBar->isVisible())
46 return draggable;
47
48 auto fw = titleBar->window()->asFloatingWindowController();
49 if (!fw) // defensive, doesn't happen
50 return draggable;
51
52 if (fw->titleBar() == titleBar) {
53 // Defensive, doesn't happen
54 return draggable;
55 } else {
56 if (KDDockWidgets::usesNativeTitleBar())
57 return fw;
58 return fw->titleBar();
59 }
60 } else {
61 return draggable;
62 }
63}
64
65WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw, Draggable *draggable)
66 : m_floatingWindow(fw)
67 , m_draggable(bestDraggable(draggable))
68 , m_draggableView(m_draggable ? m_draggable->asView() : nullptr)
69 , m_guard(m_draggableView)
70{
71 init();
72 updateTransparency(/*enable=*/true);
73}
74
75WindowBeingDragged::WindowBeingDragged(Draggable *draggable)
76 : m_draggable(draggable)
77 , m_draggableView(m_draggable->asView())
78 , m_guard(m_draggableView)
79{
80 if (!isWayland()) {
81 KDDW_ERROR("Wrong ctor called."); // Doesn't happen
82 assert(false);
83 return;
84 }
85}
86
87#ifdef DOCKS_DEVELOPER_MODE
88
89// Just used by tests
90WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw)
91 : m_floatingWindow(fw)
92 , m_draggable(nullptr)
93 , m_guard(nullptr)
94{
95}
96
97#endif
98
99WindowBeingDragged::~WindowBeingDragged()
100{
101 grabMouse(false);
102 updateTransparency(/*enable=*/false);
103}
104
105void WindowBeingDragged::init()
106{
107 assert(m_floatingWindow);
108 grabMouse(true);
109 m_floatingWindow->view()->raise();
110}
111
112void WindowBeingDragged::updateTransparency(bool enable)
113{
114 // Wayland doesn't support setting opacity
115 if (!Core::Platform::hasInstance() || isWayland() || !m_floatingWindow)
116 return;
117
118 double opacity = Config::self().draggedWindowOpacity();
119 const bool transparencySupported = !std::isnan(opacity) && !fuzzyCompare(1.0, opacity);
120 if (transparencySupported) {
121 // We're using transparency, set it or unset it:
122 if (enable) {
123 if (Config::self().transparencyOnlyOverDropIndicator()) {
124 if (DragController::instance()->currentDropLocation() == DropLocation_None)
125 opacity = 1;
126 }
127 } else {
128 opacity = 1;
129 }
130
131 m_floatingWindow->view()->setWindowOpacity(opacity);
132 }
133}
134
135void WindowBeingDragged::grabMouse(bool grab)
136{
137 if (!m_guard)
138 return;
139
140 KDDW_DEBUG("WindowBeingDragged: fw={}, grab={}, draggableView={} ", ( void * )m_floatingWindow, grab, ( void * )m_draggableView);
141
142 if (grab)
143 DragController::instance()->grabMouseFor(m_draggableView);
144 else
145 DragController::instance()->releaseMouse(m_draggableView);
146}
147
148Vector<QString> WindowBeingDragged::affinities() const
149{
150 return m_floatingWindow ? m_floatingWindow->affinities() : Vector<QString>();
151}
152
153Size WindowBeingDragged::size() const
154{
155 if (m_floatingWindow)
156 return m_floatingWindow->size();
157
158 return Size();
159}
160
161Size WindowBeingDragged::minSize() const
162{
163 if (m_floatingWindow)
164 return m_floatingWindow->layout()->layoutMinimumSize();
165
166 return {};
167}
168
169Size WindowBeingDragged::maxSize() const
170{
171 if (m_floatingWindow)
172 return m_floatingWindow->layout()->layoutMaximumSizeHint();
173
174 return {};
175}
176
177bool WindowBeingDragged::contains(Layout *layout) const
178{
179 if (!layout)
180 return false;
181
182 if (m_floatingWindow)
183 return m_floatingWindow->layout() == layout;
184
185 if (auto fw = m_draggableView->rootView()->asFloatingWindowController()) {
186 // We're not dragging via the floating window itself, but via the tab bar. Still might
187 // represent floating window though.
188 return fw->layout() == layout && fw->hasSingleGroup();
189 }
190
191 return false;
192}
193
194Vector<DockWidget *> WindowBeingDragged::dockWidgets() const
195{
196 if (m_floatingWindow)
197 return m_floatingWindow->dockWidgets();
198
199 return {};
200}
201
202Draggable *WindowBeingDragged::draggable() const
203{
204 return m_draggable;
205}
206
207Pixmap WindowBeingDragged::pixmap() const
208{
209 return {};
210}
211
212FloatingWindow *WindowBeingDragged::floatingWindow() const
213{
214 return m_floatingWindow;
215}
216
217Core::View *WindowBeingDragged::floatingWindowView() const
218{
219 if (m_floatingWindow)
220 return m_floatingWindow->view();
221
222 return nullptr;
223}
224
225WindowBeingDraggedWayland::WindowBeingDraggedWayland(Draggable *draggable)
226 : WindowBeingDragged(draggable)
227{
228 if (!isWayland()) {
229 // Doesn't happen
230 KDDW_ERROR("This CTOR is only called on Wayland");
231 assert(false);
232 return;
233 }
234
235 if (auto tb = draggable->asView()->asTitleBarController()) {
236 if (auto fw = tb->floatingWindow()) {
237 // case #1: we're dragging the whole floating window by its titlebar
238 m_floatingWindow = fw;
239 } else if (Group *group = tb->group()) {
240 m_group = group;
241 } else {
242 KDDW_ERROR("Shouldn't happen. TitleBar of what ?");
243 }
244 } else if (auto fw = draggable->asView()->asFloatingWindowController()) {
245 // case #2: the floating window itself is the draggable, happens on platforms that support
246 // native dragging. Not the case for Wayland. But adding this case for completeness.
247 m_floatingWindow = fw;
248 } else if (auto tabBar = draggable->asView()->asTabBarController()) {
249 if (Platform::instance()->isQtWidgets())
250 m_dockWidget = tabBar->currentDockWidget();
251 } else if (auto stack = draggable->asView()->asStackController()) {
252 if (Platform::instance()->isQtWidgets())
253 m_group = stack->group();
254 } else {
255 KDDW_ERROR("Unknown draggable {} please fix)", ( void * )draggable);
256 }
257}
258
259WindowBeingDraggedWayland::~WindowBeingDraggedWayland()
260{
261}
262
263Pixmap WindowBeingDraggedWayland::pixmap() const
264{
265#ifdef KDDW_FRONTEND_QT
266 QPixmap pixmap(size());
267 QPainter p(&pixmap);
268 pixmap.fill(Qt::transparent);
269 p.setOpacity(0.7);
270
271 if (m_floatingWindow) {
272 m_floatingWindow->view()->render(&p);
273 } else if (m_group) {
274 m_group->view()->render(&p);
275 } else if (m_dockWidget) {
276 m_dockWidget->view()->render(&p);
277 }
278
279 return pixmap;
280#else
281 // Wayland not support on our flutter frontend yet
282 return {};
283#endif
284}
285
286Vector<QString> WindowBeingDraggedWayland::affinities() const
287{
288 if (m_floatingWindow)
289 return WindowBeingDragged::affinities();
290 else if (m_group)
291 return m_group->affinities();
292 else if (m_dockWidget)
293 return { m_dockWidget->affinities() };
294
295 return {};
296}
297
298Vector<DockWidget *> WindowBeingDraggedWayland::dockWidgets() const
299{
300 if (m_floatingWindow)
301 return WindowBeingDragged::dockWidgets();
302 else if (m_group)
303 return m_group->dockWidgets();
304 else if (m_dockWidget)
305 return { m_dockWidget };
306
307 return {};
308}
309
310bool WindowBeingDraggedWayland::isInWaylandDrag(Group *group) const
311{
312 // Returns whether the specified group is being dragged. We honour 2 cases:
313 // - The whole group is being dragged, for example a group of tabs being dragged via titlebar
314 // - A single tab is being dragged
315 return (group && m_group == group) || (m_dockWidget && m_dockWidget->dptr()->group() == group);
316}
317
318Size WindowBeingDraggedWayland::size() const
319{
320 if (m_floatingWindow)
321 return WindowBeingDragged::size();
322 else if (m_group)
323 return m_group->geometry().size();
324 else if (m_dockWidget)
325 return m_dockWidget->size();
326
327 KDDW_ERROR("Unknown size, shouldn't happen");
328 return Size();
329}
330
331Size WindowBeingDraggedWayland::minSize() const
332{
333 if (m_floatingWindow) {
334 return WindowBeingDragged::minSize();
335 } else if (m_group) {
336 return m_group->view()->minSize();
337 } else if (m_dockWidget) {
338 return m_dockWidget->view()->minSize();
339 }
340
341 KDDW_ERROR("Unknown minSize, shouldn't happen");
342 return {};
343}
344
345Size WindowBeingDraggedWayland::maxSize() const
346{
347 if (m_floatingWindow) {
348 return WindowBeingDragged::maxSize();
349 } else if (m_group) {
350 return m_group->view()->maxSizeHint();
351 } else if (m_dockWidget) {
352 return m_dockWidget->view()->maxSizeHint();
353 }
354
355 KDDW_ERROR("Unknown maxSize, shouldn't happen");
356 return {};
357}
static Draggable * bestDraggable(Draggable *draggable)
double draggedWindowOpacity() const
returns the opacity to use when dragging dock widgets By default it's 1.0, fully opaque
Definition Config.cpp:240
static Config & self()
returns the singleton Config instance
Definition Config.cpp:88
The widget (QWidget or QQuickItem) which holds a layout of dock widgets.
Definition Layout.h:57
static Platform * instance()
Returns the platform singleton.
static bool hasInstance()
Returns whether a Platform instance exists.
Class to abstract QAction, so code still works with QtQuick and Flutter.
bool fuzzyCompare(double a, double b, double epsilon=0.0001)
transparent

© 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