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"
29 #include <QGuiApplication>
32 #ifdef KDDOCKWIDGETS_QTWIDGETS
33 #include "DebugWindow_p.h"
42 #if defined(KDDOCKWIDGETS_STATICLIB) || defined(QT_STATIC)
43 Q_INIT_RESOURCE(kddockwidgets_resources);
44 #if defined(KDDOCKWIDGETS_QTQUICK)
45 Q_INIT_RESOURCE(kddockwidgets_qtquick);
50 DockRegistry::DockRegistry(
QObject *parent)
55 #ifdef KDDOCKWIDGETS_QTWIDGETS
57 #ifdef DOCKS_DEVELOPER_MODE
58 if (qEnvironmentVariableIntValue(
"KDDOCKWIDGETS_SHOW_DEBUG_WINDOW") == 1) {
59 auto dv =
new Debug::DebugWindow();
66 QQuickWindow::setDefaultAlphaBuffer(
true);
70 this, &DockRegistry::onFocusObjectChanged);
75 DockRegistry::~DockRegistry()
79 void DockRegistry::maybeDelete()
85 void DockRegistry::onFocusObjectChanged(
QObject *obj)
87 auto p = qobject_cast<WidgetType *>(obj);
89 if (
auto frame = qobject_cast<Frame *>(p)) {
93 if (
auto dw = frame->currentDockWidget()) {
94 setFocusedDockWidget(dw);
100 if (
auto dw = qobject_cast<DockWidgetBase *>(p)) {
101 DockRegistry::self()->setFocusedDockWidget(dw);
104 p = KDDockWidgets::Private::parentWidget(p);
107 setFocusedDockWidget(
nullptr);
112 if (m_focusedDockWidget.data() == dw)
115 if (m_focusedDockWidget)
116 Q_EMIT m_focusedDockWidget->isFocusedChanged(
false);
118 m_focusedDockWidget = dw;
120 if (m_focusedDockWidget)
124 bool DockRegistry::isEmpty(
bool excludeBeingDeleted)
const
126 if (!m_dockWidgets.isEmpty() || !m_mainWindows.isEmpty())
129 return excludeBeingDeleted ? !hasFloatingWindows()
130 : m_floatingWindows.isEmpty();
133 void DockRegistry::checkSanityAll(
bool dumpLayout)
135 for (
auto layout : qAsConst(m_layouts)) {
136 layout->checkSanity();
138 layout->dumpLayout();
142 bool DockRegistry::isProcessingAppQuitEvent()
const
144 return m_isProcessingAppQuitEvent;
152 for (
const QString &a1 : affinities1) {
153 for (
const QString &a2 : affinities2) {
165 names.
reserve(m_mainWindows.size());
166 for (
auto mw : m_mainWindows)
175 names.
reserve(m_dockWidgets.size());
176 for (
auto dw : m_dockWidgets)
182 bool DockRegistry::isProbablyObscured(
QWindow *window, FloatingWindow *exclude)
const
188 for (FloatingWindow *fw : m_floatingWindows) {
189 QWindow *fwWindow = fw->QWidgetAdapter::windowHandle();
190 if (fw == exclude || fwWindow == window)
200 const bool targetIsToolWindow = KDDockWidgets::usesUtilityWindows() && floatingWindowForHandle(window) !=
nullptr;
203 QWindow *mwWindow = mw->window()->windowHandle();
205 if (mwWindow && mwWindow != window && !targetIsToolWindow && mwWindow->
geometry().
intersects(geo)) {
214 bool DockRegistry::isProbablyObscured(
QWindow *target, WindowBeingDragged *exclude)
const
216 FloatingWindow *fw = exclude ? exclude->floatingWindow()
219 return isProbablyObscured(target, fw);
224 if (SideBar *sb = sideBarForDockWidget(dw))
225 return sb->location();
227 return SideBarLocation::None;
230 SideBar *DockRegistry::sideBarForDockWidget(
const DockWidgetBase *dw)
const
232 for (
auto mw : m_mainWindows) {
233 if (SideBar *sb = mw->sideBarForDockWidget(dw))
240 Frame *DockRegistry::frameInMDIResize()
const
242 for (
auto mw : m_mainWindows) {
246 LayoutWidget *layout = mw->layoutWidget();
248 for (Frame *frame : frames) {
249 if (WidgetResizeHandler *wrh = frame->resizeHandler()) {
250 if (wrh->isResizing())
262 result.
reserve(m_mainWindows.size());
264 for (
auto mw : m_mainWindows) {
266 if (affinitiesMatch(mwAffinities, affinities))
273 LayoutWidget *DockRegistry::layoutForItem(
const Layouting::Item *item)
const
275 if (!item->hostWidget())
278 if (
auto ms = qobject_cast<LayoutWidget *>(item->hostWidget()->asQObject()))
284 bool DockRegistry::itemIsInMainWindow(
const Layouting::Item *item)
const
286 if (
auto layout = layoutForItem(item))
287 return layout->isInMainWindow();
292 DockRegistry *DockRegistry::self()
296 if (!s_dockRegistry) {
297 s_dockRegistry =
new DockRegistry();
300 return s_dockRegistry;
306 qWarning() << Q_FUNC_INFO <<
"DockWidget" << dock <<
" doesn't have an ID";
307 }
else if (
auto other = dockByName(dock->
uniqueName())) {
308 qWarning() << Q_FUNC_INFO <<
"Another DockWidget" << other <<
"with name" << dock->
uniqueName() <<
" already exists." << dock;
311 m_dockWidgets << dock;
316 if (m_focusedDockWidget == dock)
317 m_focusedDockWidget =
nullptr;
319 m_dockWidgets.removeOne(dock);
326 qWarning() << Q_FUNC_INFO <<
"MainWindow" << mainWindow <<
" doesn't have an ID";
327 }
else if (
auto other = mainWindowByName(mainWindow->
uniqueName())) {
328 qWarning() << Q_FUNC_INFO <<
"Another MainWindow" << other <<
"with name" << mainWindow->
uniqueName() <<
" already exists." << mainWindow;
331 m_mainWindows << mainWindow;
334 void DockRegistry::unregisterMainWindow(
MainWindowBase *mainWindow)
336 m_mainWindows.removeOne(mainWindow);
340 void DockRegistry::registerFloatingWindow(FloatingWindow *window)
342 m_floatingWindows << window;
345 void DockRegistry::unregisterFloatingWindow(FloatingWindow *window)
347 m_floatingWindows.removeOne(window);
351 void DockRegistry::registerLayout(LayoutWidget *layout)
356 void DockRegistry::unregisterLayout(LayoutWidget *layout)
358 m_layouts.removeOne(layout);
361 void DockRegistry::registerFrame(Frame *frame)
366 void DockRegistry::unregisterFrame(Frame *frame)
368 m_frames.removeOne(frame);
373 return m_focusedDockWidget;
376 bool DockRegistry::containsDockWidget(
const QString &uniqueName)
const
378 return dockByName(uniqueName) !=
nullptr;
381 bool DockRegistry::containsMainWindow(
const QString &uniqueName)
const
383 return mainWindowByName(uniqueName) !=
nullptr;
388 for (
auto dock : qAsConst(m_dockWidgets)) {
393 if (flags.testFlag(DockByNameFlag::ConsultRemapping)) {
395 const QString newName = m_dockWidgetIdRemapping.value(name);
397 return dockByName(newName);
400 if (flags.testFlag(DockByNameFlag::CreateIfNotFound)) {
402 if (
auto factoryFunc = Config::self().dockWidgetFactoryFunc()) {
403 auto dw = factoryFunc(name);
408 m_dockWidgetIdRemapping.insert(name, dw->
uniqueName());
412 qWarning() << Q_FUNC_INFO <<
"Couldn't find dock widget" << name;
421 for (
auto mainWindow : qAsConst(m_mainWindows)) {
431 return qobject_cast<MainWindowMDI *>(mainWindowByName(name));
440 if (dw->
widget() == guest)
447 bool DockRegistry::isSane()
const
450 for (
auto dock : qAsConst(m_dockWidgets)) {
453 qWarning() <<
"DockRegistry::isSane: DockWidget" << dock <<
"is missing a name";
456 qWarning() <<
"DockRegistry::isSane: dockWidgets with duplicate names:" << name;
464 for (
auto mainwindow : qAsConst(m_mainWindows)) {
465 const QString name = mainwindow->uniqueName();
467 qWarning() <<
"DockRegistry::isSane: MainWindow" << mainwindow <<
"is missing a name";
470 qWarning() <<
"DockRegistry::isSane: mainWindow with duplicate names:" << name;
476 if (!mainwindow->multiSplitter()->checkSanity())
485 return m_dockWidgets;
493 for (
auto dw : qAsConst(m_dockWidgets)) {
506 for (
auto mw : qAsConst(m_mainWindows)) {
507 if (names.
contains(mw->uniqueName()))
517 result.
reserve(m_dockWidgets.size());
520 if (dw->parent() ==
nullptr && !dw->isVisible())
529 return m_mainWindows;
537 const Frame::List DockRegistry::frames()
const
546 result.
reserve(m_floatingWindows.size());
547 for (FloatingWindow *fw : m_floatingWindows) {
548 if (includeBeingDeleted || !fw->beingDeleted())
558 windows.
reserve(m_floatingWindows.size());
559 for (FloatingWindow *fw : m_floatingWindows) {
560 if (!fw->beingDeleted()) {
561 if (
QWindow *window = fw->windowHandle()) {
562 window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(fw));
565 qWarning() << Q_FUNC_INFO <<
"FloatingWindow doesn't have QWindow";
573 bool DockRegistry::hasFloatingWindows()
const
575 return std::any_of(m_floatingWindows.begin(), m_floatingWindows.end(), [](FloatingWindow *fw) {
576 return !fw->beingDeleted();
580 QWindow *DockRegistry::windowForHandle(WId
id)
const
582 const QWindowList windows = qApp->topLevelWindows();
584 if (w->isVisible() && w->handle()) {
585 if (w->winId() ==
id)
592 FloatingWindow *DockRegistry::floatingWindowForHandle(
QWindow *windowHandle)
const
594 for (FloatingWindow *fw : m_floatingWindows) {
595 if (fw->windowHandle() == windowHandle)
602 FloatingWindow *DockRegistry::floatingWindowForHandle(WId hwnd)
const
604 for (FloatingWindow *fw : m_floatingWindows) {
605 if (fw->windowHandle() && fw->windowHandle()->winId() == hwnd)
615 if (mw->windowHandle() == windowHandle)
624 if (
auto fw = floatingWindowForHandle(windowHandle))
627 if (
auto mw = mainWindowForHandle(windowHandle))
636 windows.
reserve(m_floatingWindows.size() + m_mainWindows.size());
638 if (!excludeFloatingDocks) {
639 for (FloatingWindow *fw : m_floatingWindows) {
640 if (fw->isVisible()) {
641 if (
QWindow *window = fw->windowHandle()) {
642 window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(fw));
645 qWarning() << Q_FUNC_INFO <<
"FloatingWindow doesn't have QWindow";
652 if (m->isVisible()) {
653 if (
QWindow *window = m->window()->windowHandle()) {
654 window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(m));
657 qWarning() << Q_FUNC_INFO <<
"MainWindow doesn't have QWindow";
665 void DockRegistry::clear(
const QStringList &affinities)
668 clear(m_dockWidgets, m_mainWindows, affinities);
675 for (
auto dw : qAsConst(dockWidgets)) {
678 dw->d->lastPositions().removePlaceholders();
682 for (
auto mw : qAsConst(mainWindows)) {
683 if (affinities.
isEmpty() || affinitiesMatch(affinities, mw->affinities())) {
684 mw->multiSplitter()->clearLayout();
689 void DockRegistry::ensureAllFloatingWidgetsAreMorphed()
692 if (dw->window() == dw && dw->isVisible())
693 dw->d->morphIntoFloatingWindow();
697 bool DockRegistry::eventFilter(
QObject *watched,
QEvent *event)
700 m_isProcessingAppQuitEvent =
true;
701 qApp->sendEvent(qApp, event);
702 m_isProcessingAppQuitEvent =
false;
705 if (
auto windowHandle = qobject_cast<QWindow *>(watched)) {
706 if (FloatingWindow *fw = floatingWindowForHandle(windowHandle)) {
708 m_floatingWindows.removeOne(fw);
709 m_floatingWindows.append(fw);
714 if (Frame *f = parentFrame(watched)) {
720 if (!(Config::self().flags() & Config::Flag_AutoHideSupport))
723 if (qobject_cast<Frame *>(watched)) {
730 if (
auto dw = qobject_cast<DockWidgetBase *>(p))
731 return onDockWidgetPressed(dw,
static_cast<QMouseEvent *
>(event));
733 if (
auto layoutWidget = qobject_cast<LayoutWidget *>(p)) {
734 if (
auto mw = layoutWidget->mainWindow()) {
737 mw->clearSideBarOverlay();
754 #ifdef KDDOCKWIDGETS_QTWIDGETS
756 if (qApp->activePopupWidget())
766 qApp->sendEvent(overlayedDockWidget->d->frame(), ev);
772 if (dw != overlayedDockWidget) {