12 #include "DropArea_p.h"
14 #include "DockRegistry_p.h"
16 #include "DockWidgetBase_p.h"
17 #include "Draggable_p.h"
18 #include "DropIndicatorOverlayInterface_p.h"
19 #include "FloatingWindow_p.h"
22 #include "Logging_p.h"
27 #include "WindowBeingDragged_p.h"
38 : MultiSplitter(parent)
39 , m_dropIndicatorOverlay(
Config::self().frameworkWidgetFactory()->createDropIndicatorOverlay(this))
41 qCDebug(creation) <<
"DropArea";
43 #ifdef KDDOCKWIDGETS_QTWIDGETS
46 qWarning() <<
"Dropping not implement for QtQuick on Wayland yet!";
53 m_inDestructor =
true;
54 qCDebug(creation) <<
"~DropArea";
57 Frame::List DropArea::frames()
const
62 Frame *DropArea::frameContainingPos(
QPoint globalPos)
const
64 const Layouting::Item::List &items = this->items();
65 for (Layouting::Item *item : items) {
66 auto frame =
static_cast<Frame *
>(item->guestAsQObject());
67 if (!frame || !frame->QWidgetAdapter::isVisible()) {
71 if (frame->containsMouse(globalPos))
77 void DropArea::updateFloatingActions()
79 const Frame::List frames = this->frames();
80 for (Frame *frame : frames)
81 frame->updateFloatingActions();
84 Layouting::Item *DropArea::centralFrame()
const
86 for (Layouting::Item *item : this->items()) {
87 if (
auto f =
static_cast<Frame *
>(item->guestAsQObject())) {
88 if (f->isCentralFrame())
99 qWarning() << Q_FUNC_INFO <<
"Invalid parameters" << dw << relativeTo << location;
103 if ((option.
visibility == InitialVisibilityOption::StartHidden) && dw->d->frame() !=
nullptr) {
105 qWarning() << Q_FUNC_INFO <<
"Dock widget already exists in the layout";
109 if (!validateAffinity(dw))
112 Frame *frame =
nullptr;
113 Frame *relativeToFrame = relativeTo ? relativeTo->d->frame() :
nullptr;
115 dw->d->saveLastFloatingGeometry();
117 const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
120 if (containsDockWidget(dw)) {
121 Frame *oldFrame = dw->d->frame();
122 if (oldFrame->hasSingleDockWidget()) {
123 Q_ASSERT(oldFrame->containsDockWidget(dw));
127 frame = Config::self().frameworkWidgetFactory()->createFrame();
128 frame->addWidget(dw);
131 frame = Config::self().frameworkWidgetFactory()->createFrame();
132 frame->addWidget(dw);
136 addWidget(dw, location, relativeToFrame, option);
138 addWidget(frame, location, relativeToFrame, option);
141 if (hadSingleFloatingFrame && !hasSingleFloatingFrame()) {
144 updateFloatingActions();
150 return dw->d->frame() && LayoutWidget::containsFrame(dw->d->frame());
153 bool DropArea::hasSingleFloatingFrame()
const
155 const Frame::List frames = this->frames();
156 return frames.size() == 1 && frames.first()->isFloating();
161 if (
auto mw = mainWindow()) {
162 return mw->affinities();
163 }
else if (
auto fw = floatingWindow()) {
164 return fw->affinities();
172 Layouting::Item *item = itemForFrame(dw->d->frame());
174 qWarning() << Q_FUNC_INFO <<
"Item not found for" << dw << dw->d->frame();
178 layoutEqually(item->parentBoxContainer());
181 DropIndicatorOverlayInterface::DropLocation DropArea::hover(WindowBeingDragged *draggedWindow,
QPoint globalPos)
183 if (Config::self().dropIndicatorsInhibited() || !validateAffinity(draggedWindow))
184 return DropIndicatorOverlayInterface::DropLocation_None;
186 if (!m_dropIndicatorOverlay) {
187 qWarning() << Q_FUNC_INFO <<
"The frontend is missing a drop indicator overlay";
188 return DropIndicatorOverlayInterface::DropLocation_None;
191 Frame *frame = frameContainingPos(globalPos);
192 m_dropIndicatorOverlay->setWindowBeingDragged(
true);
193 m_dropIndicatorOverlay->setHoveredFrame(frame);
194 return m_dropIndicatorOverlay->hover(globalPos);
200 case DropIndicatorOverlayInterface::DropLocation_OutterLeft:
201 case DropIndicatorOverlayInterface::DropLocation_OutterTop:
202 case DropIndicatorOverlayInterface::DropLocation_OutterRight:
203 case DropIndicatorOverlayInterface::DropLocation_OutterBottom:
210 bool DropArea::drop(WindowBeingDragged *droppedWindow,
QPoint globalPos)
212 FloatingWindow *floatingWindow = droppedWindow->floatingWindow();
214 if (floatingWindow == window()) {
215 qWarning() <<
"Refusing to drop onto itself";
219 if (m_dropIndicatorOverlay->currentDropLocation() == DropIndicatorOverlayInterface::DropLocation_None) {
220 qCDebug(hovering) <<
"DropArea::drop: bailing out, drop location = none";
224 qCDebug(dropping) <<
"DropArea::drop:" << droppedWindow;
226 hover(droppedWindow, globalPos);
227 auto droploc = m_dropIndicatorOverlay->currentDropLocation();
228 Frame *acceptingFrame = m_dropIndicatorOverlay->hoveredFrame();
230 qWarning() <<
"DropArea::drop: asserted with frame=" << acceptingFrame
231 <<
"; Location=" << droploc;
235 return drop(droppedWindow, acceptingFrame, droploc);
238 bool DropArea::drop(WindowBeingDragged *draggedWindow, Frame *acceptingFrame,
239 DropIndicatorOverlayInterface::DropLocation droploc)
241 FloatingWindow *droppedWindow = draggedWindow ? draggedWindow->floatingWindow()
244 if (isWayland() && !droppedWindow) {
250 droppedWindow = draggedWindow->draggable()->makeWindow()->floatingWindow();
251 if (!droppedWindow) {
253 qWarning() << Q_FUNC_INFO <<
"Wayland: Expected window" << draggedWindow;
259 const bool needToFocusNewlyDroppedWidgets = Config::self().flags() & Config::Flag_TitleBarIsFocusable;
261 ? droppedWindow->layoutWidget()->dockWidgets()
266 case DropIndicatorOverlayInterface::DropLocation_Left:
267 case DropIndicatorOverlayInterface::DropLocation_Top:
268 case DropIndicatorOverlayInterface::DropLocation_Bottom:
269 case DropIndicatorOverlayInterface::DropLocation_Right:
270 result = drop(droppedWindow, DropIndicatorOverlayInterface::multisplitterLocationFor(droploc), acceptingFrame);
272 case DropIndicatorOverlayInterface::DropLocation_OutterLeft:
273 case DropIndicatorOverlayInterface::DropLocation_OutterTop:
274 case DropIndicatorOverlayInterface::DropLocation_OutterRight:
275 case DropIndicatorOverlayInterface::DropLocation_OutterBottom:
276 result = drop(droppedWindow, DropIndicatorOverlayInterface::multisplitterLocationFor(droploc),
nullptr);
278 case DropIndicatorOverlayInterface::DropLocation_Center:
279 qCDebug(hovering) <<
"Tabbing" << droppedWindow <<
"into" << acceptingFrame;
280 if (!validateAffinity(droppedWindow, acceptingFrame))
282 acceptingFrame->addWidget(droppedWindow);
286 qWarning() <<
"DropArea::drop: Unexpected drop location" << m_dropIndicatorOverlay->currentDropLocation();
295 if (needToFocusNewlyDroppedWidgets) {
297 if (!droppedDockWidgets.
isEmpty()) {
299 Frame *frame = droppedDockWidgets.
first()->d->frame();
303 qWarning() << Q_FUNC_INFO <<
"Nothing was dropped?";
313 qCDebug(docking) <<
"DropArea::addFrame";
315 if (
auto dock = qobject_cast<DockWidgetBase *>(droppedWindow)) {
316 if (!validateAffinity(dock))
319 auto frame = Config::self().frameworkWidgetFactory()->createFrame();
320 frame->addWidget(dock);
321 addWidget(frame, location, relativeTo, DefaultSizeMode::FairButFloor);
322 }
else if (
auto floatingWindow = qobject_cast<FloatingWindow *>(droppedWindow)) {
323 if (!validateAffinity(floatingWindow))
326 const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
327 addMultiSplitter(floatingWindow->dropArea(), location, relativeTo,
328 DefaultSizeMode::FairButFloor);
329 if (hadSingleFloatingFrame != hasSingleFloatingFrame())
330 updateFloatingActions();
332 floatingWindow->scheduleDeleteLater();
335 qWarning() <<
"Unknown dropped widget" << droppedWindow;
342 void DropArea::removeHover()
344 m_dropIndicatorOverlay->removeHover();
348 bool DropArea::validateAffinity(T *window, Frame *acceptingFrame)
const
350 if (!DockRegistry::self()->affinitiesMatch(window->affinities(), affinities())) {
354 if (acceptingFrame) {
357 if (!DockRegistry::self()->affinitiesMatch(window->affinities(), acceptingFrame->affinities())) {