18#include "core/Draggable_p.h"
19#include "core/Logging_p.h"
20#include "core/Utils_p.h"
21#include "core/layouting/Item_p.h"
22#include "core/layouting/LayoutingGuest_p.h"
23#include "core/layouting/LayoutingSeparator_p.h"
24#include "core/WindowBeingDragged_p.h"
25#include "core/DelayedCall_p.h"
28#include "core/DockWidget_p.h"
60class DropArea::Private
70 bool m_inDestructor =
false;
71 const bool m_isMDIWrapper;
73 ObjectGuard<DropIndicatorOverlay> m_dropIndicatorOverlay;
75 Core::ItemBoxContainer *m_rootItem =
nullptr;
84 , d(new Private(this, options, isMDIWrapper))
94 KDDW_TRACE(
"DropArea CTOR");
96 if (d->m_isMDIWrapper) {
97 d->m_visibleWidgetCountConnection =
Layout::d_ptr()->visibleWidgetCountChanged.connect([
this] {
100 KDDW_ERROR(
"Unexpected null wrapper dock widget");
107 dw->d->titleChanged.emit(dw->title());
115 if (d->m_centralGroup)
121 d->m_inDestructor =
true;
122 delete d->m_dropIndicatorOverlay;
124 KDDW_TRACE(
"~DropArea");
129 const Core::Item::List children = d->m_rootItem->items_recursive();
132 for (
const Core::Item *child : children) {
133 if (
auto guest = child->guest()) {
134 if (!guest->freed()) {
145Core::Group *DropArea::groupContainingPos(Point globalPos)
const
147 const Core::Item::List &
items = this->
items();
148 for (Core::Item *item :
items) {
150 if (!group || !group->isVisible()) {
154 if (group->containsMouse(globalPos))
160void DropArea::updateFloatingActions()
164 group->updateFloatingActions();
170 for (Core::Item *item :
items) {
172 if (group->isCentralGroup())
181 return d->m_dropIndicatorOverlay;
188 KDDW_ERROR(
"Invalid parameters {}, {} {}", (
void * )dw, (
void * )relativeTo, location);
192 Core::Group *relativeToGroup = relativeTo ? relativeTo->
d->group() :
nullptr;
193 Core::Item *relativeToItem = relativeToGroup ? relativeToGroup->
layoutItem() :
nullptr;
201 KDDW_ERROR(
"Invalid parameters {}, {}", (
void * )dw, location);
207 KDDW_ERROR(
"Dock widget was already opened, can't be used with InitialVisibilityOption::StartHidden");
211 if (!validateAffinity(dw))
214 Core::DockWidget::Private::UpdateActions actionsUpdater(dw);
218 dw->
d->saveLastFloatingGeometry();
248 updateFloatingActions();
260 return groups.
size() == 1 &&
groups.first()->isFloating();
271 return mw->affinities();
273 return fw->affinities();
283 KDDW_ERROR(
"Item not found for dw={}, group={}", (
void * )dw, (
void * )dw->
d->group());
292 if (
Config::self().dropIndicatorsInhibited() || !validateAffinity(draggedWindow))
295 if (!d->m_dropIndicatorOverlay) {
296 KDDW_ERROR(
"The frontend is missing a drop indicator overlay");
302 d->m_dropIndicatorOverlay->setWindowBeingDragged(
true);
303 d->m_dropIndicatorOverlay->setHoveredGroup(group);
304 draggedWindow->updateTransparency(
true);
306 return d->m_dropIndicatorOverlay->hover(globalPos);
325 Core::View *fv = droppedWindow->floatingWindowView();
328 KDDW_ERROR(
"Refusing to drop onto itself");
333 KDDW_DEBUG(
"DropArea::drop: bailing out, drop location = none");
337 KDDW_DEBUG(
"DropArea::drop: {}", (
void * )droppedWindow);
339 hover(droppedWindow, globalPos);
340 auto droploc = d->m_dropIndicatorOverlay->currentDropLocation();
341 Core::Group *acceptingGroup = d->m_dropIndicatorOverlay->hoveredGroup();
343 KDDW_ERROR(
"DropArea::drop: asserted with group={}, location={}", (
void * )acceptingGroup, droploc);
347 return drop(droppedWindow, acceptingGroup, droploc);
354 draggedWindow ? draggedWindow->floatingWindow() :
nullptr;
356 if (isWayland() && !droppedWindow) {
363 draggedWindow ? draggedWindow->draggable()->
makeWindow()->floatingWindow() :
nullptr;
364 if (!droppedWindow) {
366 KDDW_ERROR(
"Wayland: Expected window {}", (
void * )draggedWindow);
372 const bool needToFocusNewlyDroppedWidgets =
385 result =
drop(droppedWindow->
view(),
392 result =
drop(droppedWindow->
view(),
396 KDDW_DEBUG(
"Tabbing window={} into group={}", (
void * )droppedWindow, (
void * )acceptingGroup);
398 if (!validateAffinity(droppedWindow, acceptingGroup))
400 acceptingGroup->
addTab(droppedWindow);
404 KDDW_ERROR(
"DropArea::drop: Unexpected drop location = {}", d->m_dropIndicatorOverlay->currentDropLocation());
415 const bool isEGLFSRootWindow =
417 if (!isEGLFSRootWindow)
420 if (needToFocusNewlyDroppedWidgets) {
422 if (!droppedDockWidgets.
isEmpty()) {
428 KDDW_ERROR(
"Nothing was dropped?");
439 KDDW_DEBUG(
"DropArea::drop");
442 if (!validateAffinity(dock))
447 Item *relativeToItem = relativeTo ? relativeTo->
layoutItem() :
nullptr;
459 KDDW_ERROR(
"Unknown dropped widget {}", (
void * )droppedWindow);
468 d->m_dropIndicatorOverlay->removeHover();
472bool DropArea::validateAffinity(T *window,
Core::Group *acceptingGroup)
const
478 if (acceptingGroup) {
492 return d->m_isMDIWrapper;
497 if (d->m_isMDIWrapper) {
510 const bool hasPersistentCentralWidget =
512 if (hasPersistentCentralWidget) {
520 group->setObjectName(QStringLiteral(
"central group"));
526bool DropArea::validateInputs(
View *widget,
Location location,
527 const Core::Item *relativeToItem,
const InitialOption &option)
const
530 KDDW_ERROR(
"Widget is null");
539 KDDW_ERROR(
"Unknown widget type {}", (
void * )widget);
543 if (isDockWidget != isStartHidden) {
544 KDDW_ERROR(
"Wrong parameters isDockWidget={}, isStartHidden={}", isDockWidget, isStartHidden);
548 if (relativeToItem) {
550 if (relativeToGroup && relativeToGroup->view()->equals(widget)) {
551 KDDW_ERROR(
"widget can't be relative to itself");
559 KDDW_ERROR(
"DropArea::addWidget: Already contains w={}", (
void * )widget);
564 KDDW_ERROR(
"DropArea::addWidget: not adding to location None");
568 const bool relativeToThis = relativeToItem ==
nullptr;
570 KDDW_ERROR(
"DropArea::addWidget: Doesn't contain relativeTo: relativeToItem{}, options={}",
"; relativeToItem=", (
void * )relativeToItem, option);
587 group->setLayoutItem(
nullptr);
591 if (!validateInputs(w, location, relativeToItem, option))
595 relativeToItem = d->m_rootItem;
597 Core::Item *newItem =
nullptr;
605 newItem->setGuest(group->asLayoutingGuest());
609 newItem->setGuest(group->asLayoutingGuest());
610 group->addTab(dw, option);
612 newItem = ms->d->m_rootItem;
615 if (
auto fw = ms->floatingWindow()) {
616 newItem->setSize_recursive(fw->size());
623 KDDW_ERROR(
"Unknown widget added", (
void * )w);
627 assert(!newItem->geometry().isEmpty());
628 Core::ItemBoxContainer::insertItemRelativeTo(newItem, relativeToItem, location, option);
637 KDDW_DEBUG(
"DropArea::addMultiSplitter: {} {} {}", (
void * )sourceMultiSplitter, (
int )location, (
void * )relativeToGroup);
638 Item *relativeToItem = relativeToGroup ? relativeToGroup->
layoutItem() :
nullptr;
640 addWidget(sourceMultiSplitter->
view(), location, relativeToItem, option);
643 updateFloatingActions();
648 return d->m_rootItem->separators_recursive();
651int DropArea::availableLengthForOrientation(
Qt::Orientation orientation)
const
654 return availableSize().height();
656 return availableSize().width();
659Size DropArea::availableSize()
const
661 return d->m_rootItem->availableSize();
675 container->layoutEqually_recursive();
677 KDDW_ERROR(
"null container");
681void DropArea::setRootItem(Core::ItemBoxContainer *root)
684 d->m_rootItem = root;
689 return d->m_rootItem;
693 const Core::Item *relativeTo)
const
695 Core::Item item(
nullptr);
699 item.setSize(wbd->size().boundedTo(wbd->maxSize()));
700 item.setMinSize(wbd->minSize());
701 item.setMaxSizeHint(wbd->maxSize());
703 Core::ItemBoxContainer *container =
704 relativeTo ? relativeTo->parentBoxContainer() : d->m_rootItem;
706 return container->suggestedDropRect(&item, relativeTo, location);
717 return d->m_rootItem->numSideBySide_recursive(o);
722 return d->m_dropIndicatorOverlay ? d->m_dropIndicatorOverlay->currentDropLocation() :
DropLocation_None;
727 return d->m_centralGroup;
Application-wide config to tune certain behaviours of the framework.
A ScopedConnection is a RAII-style way to make sure a Connection is disconnected.
static bool isOutterLocation(DropLocation location)
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.