12 #include "DockRegistry_p.h"
15 #include "DockWidgetBase_p.h"
16 #include "FloatingWindow_p.h"
17 #include "LayoutWidget_p.h"
18 #include "Logging_p.h"
20 #include "Position_p.h"
22 #include "SideBar_p.h"
24 #include "WidgetResizeHandler_p.h"
25 #include "WindowBeingDragged_p.h"
26 #include "multisplitter/Item_p.h"
30 #include <QGuiApplication>
33 #ifdef KDDOCKWIDGETS_QTWIDGETS
34 #include "DebugWindow_p.h"
43 #if defined(KDDOCKWIDGETS_STATICLIB) || defined(QT_STATIC)
44 Q_INIT_RESOURCE(kddockwidgets_resources);
45 #if defined(KDDOCKWIDGETS_QTQUICK)
46 Q_INIT_RESOURCE(kddockwidgets_qtquick);
51 DockRegistry::DockRegistry(
QObject *parent)
56 #ifdef KDDOCKWIDGETS_QTWIDGETS
58 #ifdef DOCKS_DEVELOPER_MODE
59 if (qEnvironmentVariableIntValue(
"KDDOCKWIDGETS_SHOW_DEBUG_WINDOW") == 1) {
60 auto dv =
new Debug::DebugWindow();
67 QQuickWindow::setDefaultAlphaBuffer(
true);
71 this, &DockRegistry::onFocusObjectChanged);
76 DockRegistry::~DockRegistry()
80 void DockRegistry::maybeDelete()
86 void DockRegistry::onFocusObjectChanged(
QObject *obj)
88 auto p = qobject_cast<WidgetType *>(obj);
90 if (
auto frame = qobject_cast<Frame *>(p)) {
94 if (
auto dw = frame->currentDockWidget()) {
95 setFocusedDockWidget(dw);
101 if (
auto dw = qobject_cast<DockWidgetBase *>(p)) {
102 DockRegistry::self()->setFocusedDockWidget(dw);
105 p = KDDockWidgets::Private::parentWidget(p);
108 setFocusedDockWidget(
nullptr);
113 if (m_focusedDockWidget.data() == dw)
116 if (m_focusedDockWidget)
117 Q_EMIT m_focusedDockWidget->isFocusedChanged(
false);
119 m_focusedDockWidget = dw;
121 if (m_focusedDockWidget)
125 bool DockRegistry::isEmpty(
bool excludeBeingDeleted)
const
127 if (!m_dockWidgets.isEmpty() || !m_mainWindows.isEmpty())
130 return excludeBeingDeleted ? !hasFloatingWindows()
131 : m_floatingWindows.isEmpty();
134 void DockRegistry::checkSanityAll(
bool dumpLayout)
136 for (
auto layout : qAsConst(m_layouts)) {
137 layout->checkSanity();
139 layout->dumpLayout();
143 bool DockRegistry::isProcessingAppQuitEvent()
const
145 return m_isProcessingAppQuitEvent;
153 for (
const QString &a1 : affinities1) {
154 for (
const QString &a2 : affinities2) {
166 names.
reserve(m_mainWindows.size());
167 for (
auto mw : m_mainWindows)
176 names.
reserve(m_dockWidgets.size());
177 for (
auto dw : m_dockWidgets)
183 bool DockRegistry::isProbablyObscured(
QWindow *window, FloatingWindow *exclude)
const
189 for (FloatingWindow *fw : m_floatingWindows) {
190 QWindow *fwWindow = fw->QWidgetAdapter::windowHandle();
191 if (fw == exclude || fwWindow == window)
201 const bool targetIsToolWindow = KDDockWidgets::usesUtilityWindows() && floatingWindowForHandle(window) !=
nullptr;
204 QWindow *mwWindow = mw->window()->windowHandle();
206 if (mwWindow && mwWindow != window && !targetIsToolWindow && mwWindow->
geometry().
intersects(geo)) {
215 bool DockRegistry::isProbablyObscured(
QWindow *target, WindowBeingDragged *exclude)
const
217 FloatingWindow *fw = exclude ? exclude->floatingWindow()
220 return isProbablyObscured(target, fw);
225 if (SideBar *sb = sideBarForDockWidget(dw))
226 return sb->location();
228 return SideBarLocation::None;
231 SideBar *DockRegistry::sideBarForDockWidget(
const DockWidgetBase *dw)
const
233 for (
auto mw : m_mainWindows) {
234 if (SideBar *sb = mw->sideBarForDockWidget(dw))
241 Frame *DockRegistry::frameInMDIResize()
const
243 for (
auto mw : m_mainWindows) {
247 LayoutWidget *layout = mw->layoutWidget();
249 for (Frame *frame : frames) {
250 if (WidgetResizeHandler *wrh = frame->resizeHandler()) {
251 if (wrh->isResizing())
263 result.
reserve(m_mainWindows.size());
265 for (
auto mw : m_mainWindows) {
267 if (affinitiesMatch(mwAffinities, affinities))
274 LayoutWidget *DockRegistry::layoutForItem(
const Layouting::Item *item)
const
276 if (!item->hostWidget())
279 if (
auto ms = qobject_cast<LayoutWidget *>(item->hostWidget()->asQObject()))
285 bool DockRegistry::itemIsInMainWindow(
const Layouting::Item *item)
const
287 if (LayoutWidget *layout = layoutForItem(item)) {
288 return layout->isInMainWindow(
true);
294 DockRegistry *DockRegistry::self()
298 if (!s_dockRegistry) {
299 s_dockRegistry =
new DockRegistry();
302 return s_dockRegistry;
308 qWarning() << Q_FUNC_INFO <<
"DockWidget" << dock <<
" doesn't have an ID";
309 }
else if (
auto other = dockByName(dock->
uniqueName())) {
310 qWarning() << Q_FUNC_INFO <<
"Another DockWidget" << other <<
"with name" << dock->
uniqueName() <<
" already exists." << dock;
313 m_dockWidgets << dock;
318 if (m_focusedDockWidget == dock)
319 m_focusedDockWidget =
nullptr;
321 m_dockWidgets.removeOne(dock);
328 qWarning() << Q_FUNC_INFO <<
"MainWindow" << mainWindow <<
" doesn't have an ID";
329 }
else if (
auto other = mainWindowByName(mainWindow->
uniqueName())) {
330 qWarning() << Q_FUNC_INFO <<
"Another MainWindow" << other <<
"with name" << mainWindow->
uniqueName() <<
" already exists." << mainWindow;
333 m_mainWindows << mainWindow;
336 void DockRegistry::unregisterMainWindow(
MainWindowBase *mainWindow)
338 m_mainWindows.removeOne(mainWindow);
342 void DockRegistry::registerFloatingWindow(FloatingWindow *window)
344 m_floatingWindows << window;
347 void DockRegistry::unregisterFloatingWindow(FloatingWindow *window)
349 m_floatingWindows.removeOne(window);
353 void DockRegistry::registerLayout(LayoutWidget *layout)
358 void DockRegistry::unregisterLayout(LayoutWidget *layout)
360 m_layouts.removeOne(layout);
363 void DockRegistry::registerFrame(Frame *frame)
368 void DockRegistry::unregisterFrame(Frame *frame)
370 m_frames.removeOne(frame);
375 return m_focusedDockWidget;
378 bool DockRegistry::containsDockWidget(
const QString &uniqueName)
const
380 return dockByName(uniqueName) !=
nullptr;
383 bool DockRegistry::containsMainWindow(
const QString &uniqueName)
const
385 return mainWindowByName(uniqueName) !=
nullptr;
390 for (
auto dock : qAsConst(m_dockWidgets)) {
395 if (flags.testFlag(DockByNameFlag::ConsultRemapping)) {
397 const QString newName = m_dockWidgetIdRemapping.value(name);
399 return dockByName(newName);
402 if (flags.testFlag(DockByNameFlag::CreateIfNotFound)) {
404 if (
auto factoryFunc = Config::self().dockWidgetFactoryFunc()) {
405 auto dw = factoryFunc(name);
410 m_dockWidgetIdRemapping.insert(name, dw->
uniqueName());
414 qWarning() << Q_FUNC_INFO <<
"Couldn't find dock widget" << name;
423 for (
auto mainWindow : qAsConst(m_mainWindows)) {
433 return qobject_cast<MainWindowMDI *>(mainWindowByName(name));
442 if (dw->
widget() == guest)
449 bool DockRegistry::isSane()
const
452 for (
auto dock : qAsConst(m_dockWidgets)) {
455 qWarning() <<
"DockRegistry::isSane: DockWidget" << dock <<
"is missing a name";
458 qWarning() <<
"DockRegistry::isSane: dockWidgets with duplicate names:" << name;
466 for (
auto mainwindow : qAsConst(m_mainWindows)) {
467 const QString name = mainwindow->uniqueName();
469 qWarning() <<
"DockRegistry::isSane: MainWindow" << mainwindow <<
"is missing a name";
472 qWarning() <<
"DockRegistry::isSane: mainWindow with duplicate names:" << name;
478 if (!mainwindow->multiSplitter()->checkSanity())
487 return m_dockWidgets;
495 for (
auto dw : qAsConst(m_dockWidgets)) {
508 for (
auto mw : qAsConst(m_mainWindows)) {
509 if (names.
contains(mw->uniqueName()))
519 result.
reserve(m_dockWidgets.size());
522 if (dw->parent() ==
nullptr && !dw->isVisible())
531 return m_mainWindows;
539 const Frame::List DockRegistry::frames()
const
548 result.
reserve(m_floatingWindows.size());
549 for (FloatingWindow *fw : m_floatingWindows) {
550 if (includeBeingDeleted || !fw->beingDeleted())
560 windows.
reserve(m_floatingWindows.size());
561 for (FloatingWindow *fw : m_floatingWindows) {
562 if (!fw->beingDeleted()) {
563 if (
QWindow *window = fw->windowHandle()) {
564 window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(fw));
567 qWarning() << Q_FUNC_INFO <<
"FloatingWindow doesn't have QWindow";
575 bool DockRegistry::hasFloatingWindows()
const
577 return std::any_of(m_floatingWindows.begin(), m_floatingWindows.end(), [](FloatingWindow *fw) {
578 return !fw->beingDeleted();
582 QWindow *DockRegistry::windowForHandle(WId
id)
const
584 const QWindowList windows = qApp->topLevelWindows();
586 if (w->isVisible() && w->handle()) {
587 if (w->winId() ==
id)
594 FloatingWindow *DockRegistry::floatingWindowForHandle(
QWindow *windowHandle)
const
596 for (FloatingWindow *fw : m_floatingWindows) {
597 if (fw->windowHandle() == windowHandle)
604 FloatingWindow *DockRegistry::floatingWindowForHandle(WId hwnd)
const
606 for (FloatingWindow *fw : m_floatingWindows) {
607 if (fw->windowHandle() && fw->windowHandle()->winId() == hwnd)
617 if (mw->windowHandle() == windowHandle)
626 if (
auto fw = floatingWindowForHandle(windowHandle))
629 if (
auto mw = mainWindowForHandle(windowHandle))
638 windows.
reserve(m_floatingWindows.size() + m_mainWindows.size());
640 if (!excludeFloatingDocks) {
641 for (FloatingWindow *fw : m_floatingWindows) {
642 if (fw->isVisible()) {
643 if (
QWindow *window = fw->windowHandle()) {
644 window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(fw));
647 qWarning() << Q_FUNC_INFO <<
"FloatingWindow doesn't have QWindow";
654 if (m->isVisible()) {
655 if (
QWindow *window = m->window()->windowHandle()) {
656 window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(m));
659 qWarning() << Q_FUNC_INFO <<
"MainWindow doesn't have QWindow";
667 void DockRegistry::clear(
const QStringList &affinities)
670 clear(m_dockWidgets, m_mainWindows, affinities);
677 for (
auto dw : qAsConst(dockWidgets)) {
680 dw->d->lastPosition()->removePlaceholders();
684 for (
auto mw : qAsConst(mainWindows)) {
685 if (affinities.
isEmpty() || affinitiesMatch(affinities, mw->affinities())) {
686 mw->multiSplitter()->clearLayout();
691 void DockRegistry::ensureAllFloatingWidgetsAreMorphed()
694 if (dw->window() == dw && dw->isVisible())
695 dw->d->morphIntoFloatingWindow();
699 bool DockRegistry::eventFilter(
QObject *watched,
QEvent *event)
702 m_isProcessingAppQuitEvent =
true;
703 qApp->sendEvent(qApp, event);
704 m_isProcessingAppQuitEvent =
false;
707 if (
auto windowHandle = qobject_cast<QWindow *>(watched)) {
708 if (FloatingWindow *fw = floatingWindowForHandle(windowHandle)) {
710 m_floatingWindows.removeOne(fw);
711 m_floatingWindows.append(fw);
716 if (Frame *f = firstParentOfType<Frame>(watched)) {
722 if (!(Config::self().flags() & Config::Flag_AutoHideSupport))
725 if (qobject_cast<Frame *>(watched)) {
732 if (
auto dw = qobject_cast<DockWidgetBase *>(p))
733 return onDockWidgetPressed(dw,
static_cast<QMouseEvent *
>(event));
735 if (
auto layoutWidget = qobject_cast<LayoutWidget *>(p)) {
736 if (
auto mw = layoutWidget->mainWindow()) {
739 mw->clearSideBarOverlay();
756 #ifdef KDDOCKWIDGETS_QTWIDGETS
758 if (qApp->activePopupWidget())
768 qApp->sendEvent(overlayedDockWidget->d->frame(), ev);
774 if (dw != overlayedDockWidget) {