12#include "DockRegistry_p.h" 
   15#include "DockWidgetBase_p.h" 
   16#include "FloatingWindow_p.h" 
   17#include "LayoutWidget_p.h" 
   20#include "Position_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);
 
 
   69DockRegistry::DockRegistry(
QObject *parent)
 
   71    , m_sideBarGroupings(new SideBarGroupings())
 
   75#ifdef KDDOCKWIDGETS_QTWIDGETS 
   77#ifdef DOCKS_DEVELOPER_MODE 
   78    if (qEnvironmentVariableIntValue(
"KDDOCKWIDGETS_SHOW_DEBUG_WINDOW") == 1) {
 
   79        auto dv = 
new Debug::DebugWindow();
 
   86    QQuickWindow::setDefaultAlphaBuffer(
true);
 
   90            this, &DockRegistry::onFocusObjectChanged);
 
   95DockRegistry::~DockRegistry()
 
   97    delete m_sideBarGroupings;
 
  100void DockRegistry::maybeDelete()
 
  106void DockRegistry::onFocusObjectChanged(
QObject *obj)
 
  108    auto p = qobject_cast<WidgetType *>(obj);
 
  110        if (
auto frame = qobject_cast<Frame *>(p)) {
 
  114            if (
auto dw = frame->currentDockWidget()) {
 
  115                setFocusedDockWidget(dw);
 
  121        if (
auto dw = qobject_cast<DockWidgetBase *>(p)) {
 
  122            DockRegistry::self()->setFocusedDockWidget(dw);
 
  125        p = KDDockWidgets::Private::parentWidget(p);
 
  128    setFocusedDockWidget(
nullptr);
 
  133    if (m_focusedDockWidget.data() == dw)
 
  136    if (m_focusedDockWidget)
 
  137        Q_EMIT m_focusedDockWidget->isFocusedChanged(
false);
 
  139    m_focusedDockWidget = dw;
 
  141    if (m_focusedDockWidget)
 
  145bool DockRegistry::isEmpty(
bool excludeBeingDeleted)
 const 
  147    if (!m_dockWidgets.isEmpty() || !m_mainWindows.isEmpty())
 
  150    return excludeBeingDeleted ? !hasFloatingWindows()
 
  151                               : m_floatingWindows.isEmpty();
 
  154void DockRegistry::checkSanityAll(
bool dumpLayout)
 
  156    for (
auto layout : qAsConst(m_layouts)) {
 
  157        layout->checkSanity();
 
  159            layout->dumpLayout();
 
  163bool DockRegistry::isProcessingAppQuitEvent()
 const 
  165    return m_isProcessingAppQuitEvent;
 
  173    for (
const QString &a1 : affinities1) {
 
  174        for (
const QString &a2 : affinities2) {
 
  186    names.
reserve(m_mainWindows.size());
 
  187    for (
auto mw : m_mainWindows)
 
  188        names.push_back(mw->uniqueName());
 
  196    names.
reserve(m_dockWidgets.size());
 
  197    for (
auto dw : m_dockWidgets)
 
  198        names.push_back(dw->uniqueName());
 
  203bool DockRegistry::isProbablyObscured(
QWindow *window, FloatingWindow *exclude)
 const 
  209    for (FloatingWindow *fw : m_floatingWindows) {
 
  210        QWindow *fwWindow = fw->QWidgetAdapter::windowHandle();
 
  211        if (fw == exclude || fwWindow == window)
 
  221    auto fw = floatingWindowForHandle(window);
 
  222    const bool targetIsToolWindow = fw && fw->isUtilityWindow();
 
  225        QWindow *mwWindow = mw->window()->windowHandle();
 
  227        if (mwWindow && mwWindow != window && !targetIsToolWindow && mwWindow->
geometry().
intersects(geo)) {
 
  236bool DockRegistry::isProbablyObscured(
QWindow *target, WindowBeingDragged *exclude)
 const 
  238    FloatingWindow *fw = exclude ? exclude->floatingWindow()
 
  241    return isProbablyObscured(target, fw);
 
  246    if (SideBar *sb = sideBarForDockWidget(dw))
 
  247        return sb->location();
 
  249    return SideBarLocation::None;
 
  252SideBar *DockRegistry::sideBarForDockWidget(
const DockWidgetBase *dw)
 const 
  254    for (
auto mw : m_mainWindows) {
 
  255        if (SideBar *sb = mw->sideBarForDockWidget(dw))
 
  262Frame *DockRegistry::frameInMDIResize()
 const 
  264    for (
auto mw : m_mainWindows) {
 
  268        LayoutWidget *layout = mw->layoutWidget();
 
  270        for (Frame *frame : frames) {
 
  271            if (WidgetResizeHandler *wrh = frame->resizeHandler()) {
 
  272                if (wrh->isResizing())
 
  284    result.
reserve(m_mainWindows.size());
 
  286    for (
auto mw : m_mainWindows) {
 
  288        if (affinitiesMatch(mwAffinities, affinities))
 
  295LayoutWidget *DockRegistry::layoutForItem(
const Layouting::Item *item)
 const 
  297    if (!item->hostWidget())
 
  300    if (
auto ms = qobject_cast<LayoutWidget *>(item->hostWidget()->asQObject()))
 
  306bool DockRegistry::itemIsInMainWindow(
const Layouting::Item *item)
 const 
  308    if (LayoutWidget *layout = layoutForItem(item)) {
 
  309        return layout->isInMainWindow(
true);
 
  315DockRegistry *DockRegistry::self()
 
  319    if (!s_dockRegistry) {
 
  320        s_dockRegistry = 
new DockRegistry();
 
  323    return s_dockRegistry;
 
  329        qWarning() << Q_FUNC_INFO << 
"DockWidget" << dock << 
" doesn't have an ID";
 
  330    } 
else if (
auto other = dockByName(dock->
uniqueName())) {
 
  331        qWarning() << Q_FUNC_INFO << 
"Another DockWidget" << other << 
"with name" << dock->
uniqueName() << 
" already exists." << dock;
 
  334    m_dockWidgets << dock;
 
  339    if (m_focusedDockWidget == dock)
 
  340        m_focusedDockWidget = 
nullptr;
 
  342    m_dockWidgets.removeOne(dock);
 
  343    m_sideBarGroupings->removeFromGroupings(dock);
 
  351        qWarning() << Q_FUNC_INFO << 
"MainWindow" << mainWindow << 
" doesn't have an ID";
 
  352    } 
else if (
auto other = mainWindowByName(mainWindow->
uniqueName())) {
 
  353        qWarning() << Q_FUNC_INFO << 
"Another MainWindow" << other << 
"with name" << mainWindow->
uniqueName() << 
" already exists." << mainWindow;
 
  356    m_mainWindows << mainWindow;
 
  359void DockRegistry::unregisterMainWindow(
MainWindowBase *mainWindow)
 
  361    m_mainWindows.removeOne(mainWindow);
 
  365void DockRegistry::registerFloatingWindow(FloatingWindow *window)
 
  367    m_floatingWindows << window;
 
  370void DockRegistry::unregisterFloatingWindow(FloatingWindow *window)
 
  372    m_floatingWindows.removeOne(window);
 
  376void DockRegistry::registerLayout(LayoutWidget *layout)
 
  381void DockRegistry::unregisterLayout(LayoutWidget *layout)
 
  383    m_layouts.removeOne(layout);
 
  386void DockRegistry::registerFrame(Frame *frame)
 
  391void DockRegistry::unregisterFrame(Frame *frame)
 
  393    m_frames.removeOne(frame);
 
  398    return m_focusedDockWidget;
 
  401bool DockRegistry::containsDockWidget(
const QString &uniqueName)
 const 
  403    return dockByName(uniqueName) != 
nullptr;
 
  406bool DockRegistry::containsMainWindow(
const QString &uniqueName)
 const 
  408    return mainWindowByName(uniqueName) != 
nullptr;
 
  413    for (
auto dock : qAsConst(m_dockWidgets)) {
 
  418    if (flags.testFlag(DockByNameFlag::ConsultRemapping)) {
 
  420        const QString newName = m_dockWidgetIdRemapping.value(name);
 
  422            return dockByName(newName);
 
  425    if (flags.testFlag(DockByNameFlag::CreateIfNotFound)) {
 
  427        if (
auto factoryFunc = 
Config::self().dockWidgetFactoryFunc()) {
 
  428            auto dw = factoryFunc(name);
 
  433                m_dockWidgetIdRemapping.insert(name, dw->
uniqueName());
 
  437            qWarning() << Q_FUNC_INFO << 
"Couldn't find dock widget" << name;
 
  446    for (
auto mainWindow : qAsConst(m_mainWindows)) {
 
  456    return qobject_cast<MainWindowMDI *>(mainWindowByName(name));
 
  465        if (dw->
widget() == guest)
 
  472bool DockRegistry::isSane()
 const 
  475    for (
auto dock : qAsConst(m_dockWidgets)) {
 
  478            qWarning() << 
"DockRegistry::isSane: DockWidget" << dock << 
"is missing a name";
 
  481            qWarning() << 
"DockRegistry::isSane: dockWidgets with duplicate names:" << name;
 
  489    for (
auto mainwindow : qAsConst(m_mainWindows)) {
 
  490        const QString name = mainwindow->uniqueName();
 
  492            qWarning() << 
"DockRegistry::isSane: MainWindow" << mainwindow << 
"is missing a name";
 
  495            qWarning() << 
"DockRegistry::isSane: mainWindow with duplicate names:" << name;
 
  501        if (!mainwindow->layoutWidget()->checkSanity())
 
  510    return m_dockWidgets;
 
  518    for (
auto dw : qAsConst(m_dockWidgets)) {
 
  531    for (
auto mw : qAsConst(m_mainWindows)) {
 
  532        if (names.
contains(mw->uniqueName()))
 
  542    result.
reserve(m_dockWidgets.size());
 
  545        const bool shouldSkip = honourSkipped && (dw->
layoutSaverOptions() & DockWidgetBase::LayoutSaverOption::Skip);
 
  546        if (!shouldSkip && dw->parent() == 
nullptr && !dw->isVisible())
 
  555    return m_mainWindows;
 
  563const Frame::List DockRegistry::frames()
 const 
  572    result.
reserve(m_floatingWindows.size());
 
  573    for (FloatingWindow *fw : m_floatingWindows) {
 
  574        if (!includeBeingDeleted && fw->beingDeleted())
 
  577        if (honourSkipped && fw->allDockWidgetsHave(DockWidgetBase::LayoutSaverOption::Skip))
 
  589    windows.
reserve(m_floatingWindows.size());
 
  590    for (FloatingWindow *fw : m_floatingWindows) {
 
  591        if (!fw->beingDeleted()) {
 
  592            if (
QWindow *window = fw->windowHandle()) {
 
  593                window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(fw)); 
 
  596                qWarning() << Q_FUNC_INFO << 
"FloatingWindow doesn't have QWindow";
 
  604bool DockRegistry::hasFloatingWindows()
 const 
  606    return std::any_of(m_floatingWindows.begin(), m_floatingWindows.end(), [](FloatingWindow *fw) {
 
  607        return !fw->beingDeleted();
 
  611QWindow *DockRegistry::windowForHandle(WId 
id)
 const 
  613    const QWindowList windows = qApp->topLevelWindows();
 
  615        if (w->isVisible() && w->handle()) {
 
  616            if (w->winId() == 
id)
 
  623FloatingWindow *DockRegistry::floatingWindowForHandle(
QWindow *windowHandle)
 const 
  625    for (FloatingWindow *fw : m_floatingWindows) {
 
  626        if (fw->windowHandle() == windowHandle)
 
  633FloatingWindow *DockRegistry::floatingWindowForHandle(WId hwnd)
 const 
  635    for (FloatingWindow *fw : m_floatingWindows) {
 
  636        if (fw->windowHandle() && fw->windowHandle()->winId() == hwnd)
 
  646        if (mw->windowHandle() == windowHandle)
 
  655    if (
auto fw = floatingWindowForHandle(windowHandle))
 
  658    if (
auto mw = mainWindowForHandle(windowHandle))
 
  667    windows.
reserve(m_floatingWindows.size() + m_mainWindows.size());
 
  669    if (!excludeFloatingDocks) {
 
  670        for (FloatingWindow *fw : m_floatingWindows) {
 
  671            if (fw->isVisible()) {
 
  672                if (
QWindow *window = fw->windowHandle()) {
 
  673                    window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(fw)); 
 
  676                    qWarning() << Q_FUNC_INFO << 
"FloatingWindow doesn't have QWindow";
 
  683        if (m->isVisible()) {
 
  684            if (
QWindow *window = m->window()->windowHandle()) {
 
  685                window->setProperty(
"kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick *>(m));
 
  688                qWarning() << Q_FUNC_INFO << 
"MainWindow doesn't have QWindow";
 
  696void DockRegistry::clear(
const QStringList &affinities)
 
  699    clear(m_dockWidgets, m_mainWindows, affinities);
 
  706    for (
auto dw : qAsConst(dockWidgets)) {
 
  709            dw->d->lastPosition()->removePlaceholders();
 
  713    for (
auto mw : qAsConst(mainWindows)) {
 
  714        if (affinities.
isEmpty() || affinitiesMatch(affinities, mw->affinities())) {
 
  715            mw->layoutWidget()->clearLayout();
 
  720void DockRegistry::ensureAllFloatingWidgetsAreMorphed()
 
  723        if (dw->window() == dw && dw->isVisible())
 
  724            dw->d->morphIntoFloatingWindow();
 
  728bool DockRegistry::eventFilter(
QObject *watched, 
QEvent *event)
 
  731        m_isProcessingAppQuitEvent = 
true;
 
  732        qApp->sendEvent(qApp, event);
 
  733        m_isProcessingAppQuitEvent = 
false;
 
  736        if (
auto windowHandle = qobject_cast<QWindow *>(watched)) {
 
  737            if (FloatingWindow *fw = floatingWindowForHandle(windowHandle)) {
 
  739                m_floatingWindows.removeOne(fw);
 
  740                m_floatingWindows.append(fw);
 
  745        if (Frame *f = firstParentOfType<Frame>(watched)) {
 
  754        if (qobject_cast<Frame *>(watched)) {
 
  761            if (
auto dw = qobject_cast<DockWidgetBase *>(p))
 
  762                return onDockWidgetPressed(dw, 
static_cast<QMouseEvent *
>(event));
 
  764            if (
auto layoutWidget = qobject_cast<LayoutWidget *>(p)) {
 
  765                if (
auto mw = layoutWidget->mainWindow()) {
 
  768                    mw->clearSideBarOverlay();
 
  785#ifdef KDDOCKWIDGETS_QTWIDGETS 
  787    if (qApp->activePopupWidget())
 
  797        qApp->sendEvent(overlayedDockWidget->d->frame(), ev);
 
  803        if (dw != overlayedDockWidget) {
 
  815    m_sideBarGroupings->addGrouping(dws);
 
  820    m_sideBarGroupings->removeGrouping(dws);
 
  825    return m_sideBarGroupings->groupingFor(dw);
 
  830    if (dws.
size() < 2) {
 
  840    m_groupings.removeAll(dws);
 
  845    return const_cast<SideBarGroupings *
>(
this)->groupingByRef(dw);
 
  851        auto &grouping = groupingByRef(dw);
 
  852        if (grouping.isEmpty())
 
  854        grouping.removeAll(dw);
 
  862    for (
auto &grouping : m_groupings) {
 
  863        if (grouping.contains(dw))
 
Application-wide config to tune certain behaviours of the framework.
static void initKDDockWidgetResources()
MainWindow sub-class which uses MDI as a layout.
Namespace-level methods related to registering QML types.
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
DockWidgetBase * overlayedDockWidget() const
returns the dock widget which is currently overlayed. nullptr if none. This is only relevant when usi...
Q_INVOKABLE void clearSideBarOverlay(bool deleteFrame=true)
closes any overlayed dock widget. The sidebar still displays them as button.
MainWindow sub-class which uses MDI as a layout.
bool isAccepted() const const
QEvent::Type type() const const
void focusObjectChanged(QObject *focusObject)
bool isEmpty() const const
void installEventFilter(QObject *filterObj)
bool intersects(const QRect &rectangle) const const
bool contains(const T &value) const const
QSet::iterator insert(const T &value)
bool isEmpty() const const
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
void push_back(const T &value)
QRect geometry() const const