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"
25#include "multisplitter/Item_p.h"
26#include "WindowBeingDragged_p.h"
37 : MultiSplitter(parent)
38 , m_isMDIWrapper(isMDIWrapper)
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!";
51 connect(
this, &MultiSplitter::visibleWidgetCountChanged,
this, [
this] {
52 auto dw = mdiDockWidgetWrapper();
54 qWarning() << Q_FUNC_INFO <<
"Unexpected null wrapper dock widget";
58 if (visibleCount() > 0) {
60 Q_EMIT dw->titleChanged(dw->title());
71 m_inDestructor =
true;
72 qCDebug(creation) <<
"~DropArea";
75Frame::List DropArea::frames()
const
80Frame *DropArea::frameContainingPos(
QPoint globalPos)
const
82 const Layouting::Item::List &items = this->items();
83 for (Layouting::Item *item : items) {
84 auto frame =
static_cast<Frame *
>(item->guestAsQObject());
85 if (!frame || !frame->QWidgetAdapter::isVisible()) {
89 if (frame->containsMouse(globalPos))
95void DropArea::updateFloatingActions()
97 const Frame::List frames = this->frames();
98 for (Frame *frame : frames)
99 frame->updateFloatingActions();
102Layouting::Item *DropArea::centralFrame()
const
104 for (Layouting::Item *item : this->items()) {
105 if (
auto f =
static_cast<Frame *
>(item->guestAsQObject())) {
106 if (f->isCentralFrame())
117 qWarning() << Q_FUNC_INFO <<
"Invalid parameters" << dw << relativeTo << location;
121 if ((option.
visibility == InitialVisibilityOption::StartHidden) && dw->d->frame() !=
nullptr) {
123 qWarning() << Q_FUNC_INFO <<
"Dock widget already exists in the layout";
127 if (!validateAffinity(dw))
130 Frame *frame =
nullptr;
131 Frame *relativeToFrame = relativeTo ? relativeTo->d->frame() :
nullptr;
133 dw->d->saveLastFloatingGeometry();
135 const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
138 if (containsDockWidget(dw)) {
139 Frame *oldFrame = dw->d->frame();
140 if (oldFrame->hasSingleDockWidget()) {
141 Q_ASSERT(oldFrame->containsDockWidget(dw));
146 frame->addWidget(dw);
150 frame->addWidget(dw);
154 addWidget(dw, location, relativeToFrame, option);
156 addWidget(frame, location, relativeToFrame, option);
159 if (hadSingleFloatingFrame && !hasSingleFloatingFrame()) {
162 updateFloatingActions();
168 return dw->d->frame() && LayoutWidget::containsFrame(dw->d->frame());
171bool DropArea::hasSingleFloatingFrame()
const
173 const Frame::List frames = this->frames();
174 return frames.size() == 1 && frames.first()->isFloating();
177bool DropArea::hasSingleFrame()
const
179 return visibleCount() == 1;
184 if (
auto mw = mainWindow()) {
185 return mw->affinities();
186 }
else if (
auto fw = floatingWindow()) {
187 return fw->affinities();
195 Layouting::Item *item = itemForFrame(dw->d->frame());
197 qWarning() << Q_FUNC_INFO <<
"Item not found for" << dw << dw->d->frame();
201 layoutEqually(item->parentBoxContainer());
206 if (
Config::self().dropIndicatorsInhibited() || !validateAffinity(draggedWindow))
209 if (!m_dropIndicatorOverlay) {
210 qWarning() << Q_FUNC_INFO <<
"The frontend is missing a drop indicator overlay";
214 Frame *frame = frameContainingPos(globalPos);
215 m_dropIndicatorOverlay->setWindowBeingDragged(
true);
216 m_dropIndicatorOverlay->setHoveredFrame(frame);
217 return m_dropIndicatorOverlay->hover(globalPos);
233bool DropArea::drop(WindowBeingDragged *droppedWindow,
QPoint globalPos)
235 FloatingWindow *floatingWindow = droppedWindow->floatingWindow();
237 if (floatingWindow == window()) {
238 qWarning() <<
"Refusing to drop onto itself";
243 qCDebug(hovering) <<
"DropArea::drop: bailing out, drop location = none";
247 qCDebug(dropping) <<
"DropArea::drop:" << droppedWindow;
249 hover(droppedWindow, globalPos);
250 auto droploc = m_dropIndicatorOverlay->currentDropLocation();
251 Frame *acceptingFrame = m_dropIndicatorOverlay->hoveredFrame();
253 qWarning() <<
"DropArea::drop: asserted with frame=" << acceptingFrame
254 <<
"; Location=" << droploc;
258 return drop(droppedWindow, acceptingFrame, droploc);
261bool DropArea::drop(WindowBeingDragged *draggedWindow, Frame *acceptingFrame,
264 FloatingWindow *droppedWindow = draggedWindow ? draggedWindow->floatingWindow()
267 if (isWayland() && !droppedWindow) {
273 droppedWindow = draggedWindow ? draggedWindow->draggable()->makeWindow()->floatingWindow()
275 if (!droppedWindow) {
277 qWarning() << Q_FUNC_INFO <<
"Wayland: Expected window" << draggedWindow;
285 ? droppedWindow->layoutWidget()->dockWidgets()
294 result = drop(droppedWindow, DropIndicatorOverlayInterface::multisplitterLocationFor(droploc), acceptingFrame);
300 result = drop(droppedWindow, DropIndicatorOverlayInterface::multisplitterLocationFor(droploc),
nullptr);
303 qCDebug(hovering) <<
"Tabbing" << droppedWindow <<
"into" << acceptingFrame;
304 if (!validateAffinity(droppedWindow, acceptingFrame))
306 acceptingFrame->addWidget(droppedWindow);
310 qWarning() <<
"DropArea::drop: Unexpected drop location" << m_dropIndicatorOverlay->currentDropLocation();
320 const bool isEGLFSRootWindow = isEGLFS() && (window()->isFullScreen() || window()->isMaximized());
321 if (!isEGLFSRootWindow)
324 if (needToFocusNewlyDroppedWidgets) {
326 if (!droppedDockWidgets.
isEmpty()) {
328 Frame *frame = droppedDockWidgets.
first()->d->frame();
332 qWarning() << Q_FUNC_INFO <<
"Nothing was dropped?";
342 qCDebug(docking) <<
"DropArea::addFrame";
344 if (
auto dock = qobject_cast<DockWidgetBase *>(droppedWindow)) {
345 if (!validateAffinity(dock))
349 frame->addWidget(dock);
350 addWidget(frame, location, relativeTo, DefaultSizeMode::FairButFloor);
351 }
else if (
auto floatingWindow = qobject_cast<FloatingWindow *>(droppedWindow)) {
352 if (!validateAffinity(floatingWindow))
355 const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
356 addMultiSplitter(floatingWindow->dropArea(), location, relativeTo,
357 DefaultSizeMode::FairButFloor);
358 if (hadSingleFloatingFrame != hasSingleFloatingFrame())
359 updateFloatingActions();
361 floatingWindow->scheduleDeleteLater();
364 qWarning() <<
"Unknown dropped widget" << droppedWindow;
371void DropArea::removeHover()
373 m_dropIndicatorOverlay->removeHover();
377bool DropArea::validateAffinity(T *window, Frame *acceptingFrame)
const
379 if (!DockRegistry::self()->affinitiesMatch(window->affinities(), affinities())) {
383 if (acceptingFrame) {
386 if (!DockRegistry::self()->affinitiesMatch(window->affinities(), acceptingFrame->affinities())) {
394bool DropArea::isMDIWrapper()
const
396 return m_isMDIWrapper;
402 return qobject_cast<DockWidgetBase *>(QWidgetAdapter::parent());
Application-wide config to tune certain behaviours of the framework.
static bool isOutterLocation(DropLocation location)
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
bool isEmpty() const const