KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
DropIndicatorOverlayInterface.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 "DropIndicatorOverlayInterface_p.h"
13
14#include "Frame_p.h"
15#include "DropArea_p.h"
16#include "DockRegistry_p.h"
17#include "DragController_p.h"
18#include "Config.h"
19
20using namespace KDDockWidgets;
21
22DropIndicatorOverlayInterface::DropIndicatorOverlayInterface(DropArea *dropArea)
23 : QWidgetAdapter(dropArea)
24 , m_dropArea(dropArea)
25{
26 setVisible(false);
27 setObjectName(QStringLiteral("DropIndicatorOverlayInterface"));
28
29 // Set transparent for mouse events so that topLevel->childAt() never returns the drop indicator overlay
31
32 connect(DockRegistry::self(), &DockRegistry::dropIndicatorsInhibitedChanged, this,
33 [this](bool inhibited) {
34 if (inhibited) {
35 removeHover();
36 } else {
37 // Re-add hover. Fastest way is simply faking a mouse move
38 if (auto state = qobject_cast<StateDragging *>(DragController::instance()->activeState())) {
39 state->handleMouseMove(QCursor::pos());
40 }
41 }
42 });
43}
44
45void DropIndicatorOverlayInterface::setWindowBeingDragged(bool is)
46{
47 if (is == m_draggedWindowIsHovering)
48 return;
49
50 m_draggedWindowIsHovering = is;
51 if (is) {
52 setGeometry(m_dropArea->QWidgetAdapter::rect());
53 raise();
54 } else {
55 setHoveredFrame(nullptr);
56 }
57
58 setVisible(is);
59 updateVisibility();
60}
61
62QRect DropIndicatorOverlayInterface::hoveredFrameRect() const
63{
64 return m_hoveredFrameRect;
65}
66
67void DropIndicatorOverlayInterface::setHoveredFrame(Frame *frame)
68{
69 if (frame == m_hoveredFrame)
70 return;
71
72 if (WindowBeingDragged *wbd = DragController::instance()->windowBeingDragged()) {
73 if (wbd->isInWaylandDrag(frame)) {
74 // With wayland, we don't detach the group before the mouse release.
75 // Instead, we start a QDrag, with this group as cursor QPixmap.
76 // Here we catch the case where we're dragging the pixmap onto the group
77 // where're already dragging. That's a no-op.
78 return;
79 }
80 }
81
82 if (m_hoveredFrame)
83 disconnect(m_hoveredFrame, &QObject::destroyed, this, &DropIndicatorOverlayInterface::onFrameDestroyed);
84
85 m_hoveredFrame = frame;
86 if (m_hoveredFrame) {
87 connect(frame, &QObject::destroyed, this, &DropIndicatorOverlayInterface::onFrameDestroyed);
88 setHoveredFrameRect(m_hoveredFrame->QWidgetAdapter::geometry());
89 } else {
90 setHoveredFrameRect(QRect());
91 }
92
93 updateVisibility();
94 Q_EMIT hoveredFrameChanged(m_hoveredFrame);
95 onHoveredFrameChanged(m_hoveredFrame);
96}
97
98bool DropIndicatorOverlayInterface::isHovered() const
99{
100 return m_draggedWindowIsHovering;
101}
102
103DropLocation DropIndicatorOverlayInterface::currentDropLocation() const
104{
105 return m_currentDropLocation;
106}
107
108KDDockWidgets::Location DropIndicatorOverlayInterface::multisplitterLocationFor(DropLocation dropLoc)
109{
110 switch (dropLoc) {
117 case DropLocation_Top:
131 qWarning() << Q_FUNC_INFO << "Unexpected drop location" << dropLoc;
132 break;
133 }
134
136}
137
138bool DropIndicatorOverlayInterface::dropIndicatorVisible(DropLocation dropLoc) const
139{
140 if (dropLoc == DropLocation_None)
141 return false;
142
143 WindowBeingDragged *windowBeingDragged = DragController::instance()->windowBeingDragged();
144 if (!windowBeingDragged)
145 return false;
146
147 const DockWidgetBase::List source = windowBeingDragged->dockWidgets();
148 const DockWidgetBase::List target = m_hoveredFrame ? m_hoveredFrame->dockWidgets()
150
151 const bool isInner = dropLoc & DropLocation_Inner;
152 const bool isOutter = dropLoc & DropLocation_Outter;
153 if (isInner) {
154 if (!m_hoveredFrame)
155 return false;
156 } else if (isOutter) {
157 // If there's only 1 frame in the layout, the outer indicators are redundant, as they do the same thing as the internal ones.
158 // But there might be another window obscuring our target, so it's useful to show the outer indicators in this case
159 const bool isTheOnlyFrame = m_hoveredFrame && m_hoveredFrame->isTheOnlyFrame();
160 if (isTheOnlyFrame && !DockRegistry::self()->isProbablyObscured(m_hoveredFrame->window()->windowHandle(), windowBeingDragged))
161 return false;
162 } else if (dropLoc == DropLocation_Center) {
163 if (!m_hoveredFrame || !m_hoveredFrame->isDockable())
164 return false;
165
166 if (auto tabbingAllowedFunc = Config::self().tabbingAllowedFunc()) {
167 if (!tabbingAllowedFunc(source, target))
168 return false;
169 }
170
171 // Only allow to dock to center if the affinities match
172 if (!DockRegistry::self()->affinitiesMatch(m_hoveredFrame->affinities(), windowBeingDragged->affinities()))
173 return false;
174 } else {
175 qWarning() << Q_FUNC_INFO << "Unknown drop indicator location" << dropLoc;
176 return false;
177 }
178
179 if (auto dropIndicatorAllowedFunc = Config::self().dropIndicatorAllowedFunc()) {
180 DropArea *dropArea = DragController::instance()->dropAreaUnderCursor();
181 if (!dropIndicatorAllowedFunc(dropLoc, source, target, dropArea))
182 return false;
183 }
184
185 return true;
186}
187
188void DropIndicatorOverlayInterface::onFrameDestroyed()
189{
190 setHoveredFrame(nullptr);
191}
192
193void DropIndicatorOverlayInterface::onHoveredFrameChanged(Frame *)
194{
195}
196
197void DropIndicatorOverlayInterface::setCurrentDropLocation(DropLocation location)
198{
199 if (m_currentDropLocation != location) {
200 m_currentDropLocation = location;
201 Q_EMIT currentDropLocationChanged();
202 }
203}
204
205DropLocation DropIndicatorOverlayInterface::hover(QPoint globalPos)
206{
207 return hover_impl(globalPos);
208}
209
210void DropIndicatorOverlayInterface::setHoveredFrameRect(QRect rect)
211{
212 if (m_hoveredFrameRect != rect) {
213 m_hoveredFrameRect = rect;
214 Q_EMIT hoveredFrameRectChanged();
215 }
216}
217
218void DropIndicatorOverlayInterface::removeHover()
219{
220 setWindowBeingDragged(false);
221 setCurrentDropLocation(DropLocation_None);
222}
Application-wide config to tune certain behaviours of the framework.
static Config & self()
returns the singleton Config instance
Definition Config.cpp:84
QVector< DockWidgetBase * > List
@ Location_OnTop
‍Left docking location
@ Location_OnRight
‍Top docking location
@ Location_OnBottom
‍Right docking location
DropLocation
Enum describing the different drop indicator types.
QPoint pos()
void destroyed(QObject *obj)
WA_TransparentForMouseEvents

© 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