KDDockWidgets API Documentation  1.5
WindowBeingDragged.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-2022 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 
27 using namespace KDDockWidgets;
28 
29 static 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 
58 WindowBeingDragged::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 
73 WindowBeingDragged::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
87 WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw)
88  : m_floatingWindow(fw)
89  , m_draggable(nullptr)
90 {
91 }
92 
93 #endif
94 
95 WindowBeingDragged::~WindowBeingDragged()
96 {
97  grabMouse(false);
98 
99  if (!isWayland()) { // 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 
107 void WindowBeingDragged::init()
108 {
109  Q_ASSERT(m_floatingWindow);
110  grabMouse(true);
111  m_floatingWindow->raise();
112 }
113 
114 void 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 
126 QStringList WindowBeingDragged::affinities() const
127 {
128  return m_floatingWindow ? m_floatingWindow->affinities()
129  : QStringList();
130 }
131 
132 QSize WindowBeingDragged::size() const
133 {
134  if (m_floatingWindow)
135  return m_floatingWindow->size();
136 
137  return QSize();
138 }
139 
140 QSize WindowBeingDragged::minSize() const
141 {
142  if (m_floatingWindow)
143  return m_floatingWindow->layoutWidget()->layoutMinimumSize();
144 
145  return {};
146 }
147 
148 QSize WindowBeingDragged::maxSize() const
149 {
150  if (m_floatingWindow)
151  return m_floatingWindow->layoutWidget()->layoutMaximumSizeHint();
152 
153  return {};
154 }
155 
156 bool 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 
172 QVector<DockWidgetBase *> WindowBeingDragged::dockWidgets() const
173 {
174  if (m_floatingWindow)
175  return m_floatingWindow->dockWidgets();
176 
177  return {};
178 }
179 
180 Draggable *WindowBeingDragged::draggable() const
181 {
182  return m_draggable;
183 }
184 
185 WindowBeingDraggedWayland::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 
220 WindowBeingDraggedWayland::~WindowBeingDraggedWayland()
221 {
222 }
223 
224 QPixmap 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 
241 QStringList 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 
253 QVector<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 
265 QSize 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 
278 QSize 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 
292 QSize 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 }
Layouting::Widget::widgetMaxSize
static QSize widgetMaxSize(const T *w)
Definition: Widget.h:164
Layouting::Widget::widgetMinSize
static QSize widgetMinSize(const T *w)
Definition: Widget.h:152
QSize
QPainter
QPixmap
KDDockWidgets
Definition: Config.cpp:36
Draggable
QVector< DockWidgetBase * >
bestDraggable
static Draggable * bestDraggable(Draggable *draggable)
Definition: WindowBeingDragged.cpp:29
QStringList

© 2019-2022 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 Mon Mar 7 2022 02:01:21 for KDDockWidgets API Documentation by doxygen 1.8.20