12#include "FloatingWindow_p.h" 
   17#include "TitleBar_p.h" 
   18#include "WindowBeingDragged_p.h" 
   20#include "WidgetResizeHandler_p.h" 
   21#include "DockRegistry_p.h" 
   24#include "DragController_p.h" 
   25#include "LayoutSaver_p.h" 
   26#include "DockWidgetBase_p.h" 
   28#include "multisplitter/Item_p.h" 
   31#include <QScopedValueRollback> 
   52    if (requestedFlags & FloatingWindowFlag::UseQtTool) {
 
   57    if (requestedFlags & FloatingWindowFlag::UseQtWindow) {
 
   62    if (FloatingWindow::s_windowFlagsOverride) {
 
   64        return FloatingWindow::s_windowFlagsOverride;
 
   67    if (KDDockWidgets::usesNativeDraggingAndResizing())
 
 
   78    const FloatingWindowFlags requestedFlags = frame ? frame->requestedFloatingWindowFlags() : FloatingWindowFlag::FromGlobalConfig;
 
   79    if (requestedFlags & FloatingWindowFlag::DontUseParentForFloatingWindows) {
 
   94        return candidateParent;
 
  101    if (windows.
size() == 1) {
 
  102        return windows.
first();
 
  105        const MainWindowBase::List mainWindows = DockRegistry::self()->mainWindowsWithAffinity(affinities);
 
  108            qWarning() << Q_FUNC_INFO << 
"No window with affinity" << affinities << 
"found";
 
  111            return mainWindows.
first();
 
 
  125    if (!(requestedFlags & FloatingWindowFlag::FromGlobalConfig)) {
 
  127        return requestedFlags;
 
  132    FloatingWindowFlags flags = {};
 
  135        flags |= FloatingWindowFlag::TitleBarHasMinimizeButton;
 
  138        flags |= FloatingWindowFlag::TitleBarHasMaximizeButton;
 
  141        flags |= FloatingWindowFlag::KeepAboveIfNotUtilityWindow;
 
  144        flags |= FloatingWindowFlag::NativeTitleBar;
 
  147        flags |= FloatingWindowFlag::HideTitleBarWhenTabsVisible;
 
  150        flags |= FloatingWindowFlag::AlwaysTitleBarWhenFloating;
 
  153        flags |= FloatingWindowFlag::DontUseParentForFloatingWindows;
 
  156        flags |= FloatingWindowFlag::UseQtWindow;
 
 
  162                               FloatingWindowFlags requestedFlags)
 
  164    , Draggable(this, 
KDDockWidgets::usesNativeDraggingAndResizing()) 
 
  166    , m_dropArea(new DropArea(this))
 
  167    , m_titleBar(
Config::self().frameworkWidgetFactory()->createTitleBar(this))
 
  169    if (!suggestedGeometry.
isNull())
 
  170        setGeometry(suggestedGeometry);
 
  172    if (kddwUsesQtWidgets()) {
 
  176#ifdef KDDOCKWIDGETS_QTWIDGETS 
  177        m_nchittestFilter = 
new NCHITTESTEventFilter(
this);
 
  178        qApp->installNativeEventFilter(m_nchittestFilter);
 
  180        WidgetResizeHandler::setupWindow(windowHandle());
 
  184    DockRegistry::self()->registerFloatingWindow(
this);
 
  186    if (m_flags & FloatingWindowFlag::KeepAboveIfNotUtilityWindow)
 
  189    if (kddwUsesQtWidgets()) {
 
  191        maybeCreateResizeHandler();
 
  194    updateTitleBarVisibility();
 
  195    connect(m_dropArea, &LayoutWidget::visibleWidgetCountChanged, 
this,
 
  196            &FloatingWindow::onFrameCountChanged);
 
  197    connect(m_dropArea, &LayoutWidget::visibleWidgetCountChanged, 
this,
 
  198            &FloatingWindow::numFramesChanged);
 
  199    connect(m_dropArea, &LayoutWidget::visibleWidgetCountChanged, 
this,
 
  200            &FloatingWindow::onVisibleFrameCountChanged);
 
  201    m_layoutDestroyedConnection = connect(m_dropArea, &
QObject::destroyed, 
this, &FloatingWindow::scheduleDeleteLater);
 
  207        return FloatingWindowFlag::FromGlobalConfig;
 
  209    return frame->requestedFloatingWindowFlags();
 
 
  212FloatingWindow::FloatingWindow(Frame *frame, 
QRect suggestedGeometry, 
MainWindowBase *parent)
 
  217    if (frame->hasNestedMDIDockWidgets()) {
 
  221        if (frame->dockWidgetCount() == 0) {
 
  223            qWarning() << Q_FUNC_INFO << 
"Unexpected empty frame";
 
  228        DropArea *dropAreaMDIWrapper = dwMDIWrapper->d->mdiDropAreaWrapper();
 
  230        if (dropAreaMDIWrapper->hasSingleFrame()) {
 
  231            Frame *innerFrame = dropAreaMDIWrapper->frames().constFirst();
 
  232            if (innerFrame->hasSingleDockWidget()) {
 
  238                dw->d->lastPosition() = dwMDIWrapper->d->lastPosition();
 
  243        dwMDIWrapper->setVisible(
false);
 
  244        if (!DragController::instance()->isIdle()) {
 
  247            connect(DragController::instance(), &DragController::currentStateChanged, dwMDIWrapper, [dwMDIWrapper] {
 
  248                if (DragController::instance()->isIdle())
 
  252            dwMDIWrapper->deleteLater();
 
  263FloatingWindow::~FloatingWindow()
 
  266    disconnect(m_layoutDestroyedConnection);
 
  267    delete m_nchittestFilter;
 
  269    DockRegistry::self()->unregisterFloatingWindow(
this);
 
  272#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS) 
  273bool FloatingWindow::nativeEvent(
const QByteArray &eventType, 
void *message, Qt5Qt6Compat::qintptr *result)
 
  275    if (m_inDtor || m_deleteScheduled)
 
  278    if (KDDockWidgets::usesAeroSnapWithCustomDecos()) {
 
  280        if (WidgetResizeHandler::handleWindowsNativeEvent(
this, eventType, message, result))
 
  282    } 
else if (KDDockWidgets::usesNativeTitleBar()) {
 
  283        auto msg = 
static_cast<MSG *
>(message);
 
  284        if (msg->message == WM_SIZING) {
 
  286            Q_EMIT DragController::instance()->dragCanceled();
 
  294void FloatingWindow::maybeCreateResizeHandler()
 
  296    if (!KDDockWidgets::usesNativeDraggingAndResizing()) {
 
  299        const auto filterMode = isEGLFS() ? WidgetResizeHandler::EventFilterMode::Global
 
  300                                          : WidgetResizeHandler::EventFilterMode::Local;
 
  302        setWidgetResizeHandler(
new WidgetResizeHandler(filterMode,
 
  303                                                       WidgetResizeHandler::WindowMode::TopLevel,
 
  308std::unique_ptr<WindowBeingDragged> FloatingWindow::makeWindow()
 
  310    return std::unique_ptr<WindowBeingDragged>(
new WindowBeingDragged(
this, 
this));
 
  315    const Frame::List frames = this->frames();
 
  316    if (frames.size() == 1) {
 
  317        Frame *frame = frames.first();
 
  318        if (frame->hasSingleDockWidget())
 
  319            return frame->dockWidgetAt(0);
 
  327    return m_dropArea->dockWidgets();
 
  330const Frame::List FloatingWindow::frames()
 const 
  332    Q_ASSERT(m_dropArea);
 
  333    return m_dropArea->frames();
 
  336QSize FloatingWindow::maxSizeHint()
 const 
  338    QSize result = Layouting::Item::hardcodedMaximumSize;
 
  345    const Frame::List frames = this->frames();
 
  346    if (frames.size() == 1) {
 
  351        Frame *frame = frames[0];
 
  352        if (frame->dockWidgetCount() == 1) { 
 
  353            const QSize waste = (minimumSize() - frame->minSize()).expandedTo(
QSize(0, 0));
 
  354            result = frame->maxSizeHint() + waste;
 
  360    return result.
boundedTo(Layouting::Item::hardcodedMaximumSize);
 
  363void FloatingWindow::setSuggestedGeometry(
QRect suggestedRect, SuggestedGeometryHints hint)
 
  365    const QSize maxSize = maxSizeHint();
 
  366    const bool hasMaxSize = maxSize != Layouting::Item::hardcodedMaximumSize;
 
  373            && (m_flags & FloatingWindowFlag::NativeTitleBar)) {
 
  374            const QMargins margins = contentMargins();
 
  383    ensureRectIsOnScreen(suggestedRect);
 
  385    setGeometry(suggestedRect);
 
  388void FloatingWindow::scheduleDeleteLater()
 
  390    m_deleteScheduled = 
true;
 
  391    DockRegistry::self()->unregisterFloatingWindow(
this);
 
  395MultiSplitter *FloatingWindow::multiSplitter()
 const 
  400LayoutWidget *FloatingWindow::layoutWidget()
 const 
  405bool FloatingWindow::isInDragArea(
QPoint globalPoint)
 const 
  411    if (usesAeroSnapWithCustomDecos())
 
  412        return m_lastHitTest == HTCAPTION;
 
  415    return dragRect().contains(globalPoint);
 
  418bool FloatingWindow::anyNonClosable()
 const 
  420    for (Frame *frame : frames()) {
 
  421        if (frame->anyNonClosable())
 
  427bool FloatingWindow::anyNonDockable()
 const 
  429    for (Frame *frame : frames()) {
 
  430        if (frame->anyNonDockable())
 
  436bool FloatingWindow::hasSingleFrame()
 const 
  438    return m_dropArea->hasSingleFrame();
 
  441bool FloatingWindow::hasSingleDockWidget()
 const 
  443    const Frame::List frames = this->frames();
 
  444    if (frames.size() != 1)
 
  447    Frame *frame = frames.first();
 
  448    return frame->dockWidgetCount() == 1;
 
  451Frame *FloatingWindow::singleFrame()
 const 
  453    const Frame::List frames = this->frames();
 
  455    return frames.isEmpty() ? nullptr
 
  459bool FloatingWindow::beingDeleted()
 const 
  461    if (m_deleteScheduled || m_inDtor)
 
  465    for (Frame *f : frames()) {
 
  466        if (!f->beingDeletedLater())
 
  473void FloatingWindow::onFrameCountChanged(
int count)
 
  476        scheduleDeleteLater();
 
  478        updateTitleBarVisibility();
 
  480            dropArea()->updateFloatingActions();
 
  484void FloatingWindow::onVisibleFrameCountChanged(
int count)
 
  486    if (m_disableSetVisible)
 
  489    updateSizeConstraints();
 
  490    setVisible(count > 0);
 
  497    if (isMaximizedOverride())
 
  499    else if (isMinimizedOverride())
 
  505void FloatingWindow::updateTitleBarVisibility()
 
  507    if (m_updatingTitleBarVisibility)
 
  511    updateTitleAndIcon();
 
  515    for (Frame *frame : frames())
 
  516        frame->updateTitleBarVisibility();
 
  518    if (KDDockWidgets::usesClientTitleBar()) {
 
  519        if ((m_flags & FloatingWindowFlag::HideTitleBarWhenTabsVisible) && !(m_flags & FloatingWindowFlag::AlwaysTitleBarWhenFloating)) {
 
  520            if (hasSingleFrame()) {
 
  521                visible = !frames().first()->hasTabsVisible();
 
  525        m_titleBar->updateButtons();
 
  530    m_titleBar->setVisible(visible);
 
  535    auto frames = this->frames();
 
  536    return frames.isEmpty() ? 
QStringList() : frames.constFirst()->affinities();
 
  539void FloatingWindow::updateTitleAndIcon()
 
  543    if (hasSingleFrame()) {
 
  544        const Frame *frame = frames().constFirst();
 
  545        title = frame->title();
 
  546        icon = frame->icon();
 
  548        title = qApp->applicationName();
 
  550    m_titleBar->setTitle(title);
 
  551    m_titleBar->setIcon(icon);
 
  555    setWindowTitle(title);
 
  567    m_dropArea->onCloseEvent(e);
 
  570bool FloatingWindow::deserialize(
const LayoutSaver::FloatingWindow &fw)
 
  572    if (dropArea()->deserialize(fw.multiSplitterLayout)) {
 
  573        updateTitleBarVisibility();
 
  589LayoutSaver::FloatingWindow FloatingWindow::serialize()
 const 
  591    LayoutSaver::FloatingWindow fw;
 
  593    fw.geometry = geometry();
 
  594    fw.normalGeometry = normalGeometry();
 
  595    fw.isVisible = isVisible();
 
  596    fw.multiSplitterLayout = dropArea()->serialize();
 
  597    fw.screenIndex = screenNumberForWidget(
this);
 
  598    fw.screenSize = screenSizeForWidget(
this);
 
  599    fw.affinities = affinities();
 
  600    fw.windowState = windowStateOverride();
 
  603    auto mainWindow = qobject_cast<MainWindowBase *>(parentWidget());
 
  604    fw.parentIndex = mainWindow ? DockRegistry::self()->mainwindows().indexOf(mainWindow)
 
  610QRect FloatingWindow::dragRect()
 const 
  613    if (m_titleBar->isVisible()) {
 
  614        rect = m_titleBar->rect();
 
  616    } 
else if (hasSingleFrame()) {
 
  617        rect = frames().constFirst()->dragRect();
 
  619        qWarning() << Q_FUNC_INFO << 
"Expected a title bar";
 
  625bool FloatingWindow::event(
QEvent *ev)
 
  629        Q_EMIT activatedChanged();
 
  632        return parent()->
event(ev);
 
  634        updateSizeConstraints();
 
  637    return QWidgetAdapter::event(ev);
 
  642    const Frame::List frames = this->frames();
 
  643    return std::all_of(frames.begin(), frames.end(), [option](Frame *frame) {
 
  644        return frame->allDockWidgetsHave(option);
 
  650    const Frame::List frames = this->frames();
 
  651    return std::any_of(frames.begin(), frames.end(), [option](Frame *frame) {
 
  652        return frame->anyDockWidgetsHas(option);
 
  658    const Frame::List frames = this->frames();
 
  659    return std::all_of(frames.begin(), frames.end(), [option](Frame *frame) {
 
  660        return frame->allDockWidgetsHave(option);
 
  666    const Frame::List frames = this->frames();
 
  667    return std::any_of(frames.begin(), frames.end(), [option](Frame *frame) {
 
  668        return frame->anyDockWidgetsHas(option);
 
  675    m_dropArea->addDockWidget(dw, location, relativeTo, option);
 
  678bool FloatingWindow::isMDI()
 const 
  683bool FloatingWindow::isWindow()
 const 
  690    return qobject_cast<MainWindowBase *>(parent());
 
  693QMargins FloatingWindow::contentMargins()
 const 
  695    return { 4, 4, 4, 4 };
 
  698bool FloatingWindow::isMaximizedOverride()
 const 
  700    return QWidgetAdapter::isMaximized();
 
  703bool FloatingWindow::isMinimizedOverride()
 const 
  705    return QWidgetAdapter::isMinimized();
 
  708void FloatingWindow::showMaximized()
 
  710    QWidgetAdapter::showMaximized();
 
  713void FloatingWindow::showNormal()
 
  715    QWidgetAdapter::showNormal();
 
  718void FloatingWindow::showMinimized()
 
  720    QWidgetAdapter::showMinimized();
 
  723QRect FloatingWindow::normalGeometry()
 const 
  725    return QWidgetAdapter::normalGeometry();
 
  730    return m_lastWindowManagerState;
 
  733int FloatingWindow::userType()
 const 
  735    if (Frame *f = singleFrame())
 
  736        return f->userType();
 
  740void FloatingWindow::updateSizeConstraints()
 
  748        setMaximumSize(maxSizeHint());
 
  752void FloatingWindow::ensureRectIsOnScreen(
QRect &geometry)
 
  754    const auto screens = qApp->screens();
 
  758    int nearestDistSq = std::numeric_limits<int>::max();
 
  759    int nearestIndex = -1;
 
  761    const int screenCount = screens.count();
 
  762    for (
int i = 0; i < screenCount; i++) {
 
  763        const QRect scrGeom = screens[i]->geometry();
 
  771        const int distSq = (dist2D.
x() * dist2D.
x()) + (dist2D.
y() * dist2D.
y());
 
  772        if (distSq < nearestDistSq) {
 
  773            nearestDistSq = distSq;
 
  779    auto scrGeom = screens[nearestIndex]->geometry();
 
  780    scrGeom.
moveTopLeft(scrGeom.
topLeft() - screens[nearestIndex]->virtualGeometry().topLeft());
 
  782    if (geometry.
left() < scrGeom.
left()) {
 
  784    } 
else if (geometry.
left() > scrGeom.
right()) {
 
  788    if (geometry.
top() < scrGeom.
top()) {
 
  790    } 
else if (geometry.
top() > scrGeom.
bottom()) {
 
  795bool FloatingWindow::supportsMinimizeButton()
 const 
  797    return m_flags & FloatingWindowFlag::TitleBarHasMinimizeButton;
 
  800bool FloatingWindow::supportsMaximizeButton()
 const 
  802    return m_flags & FloatingWindowFlag::TitleBarHasMaximizeButton;
 
  805bool FloatingWindow::isUtilityWindow()
 const 
  807    const bool dontUse = (m_flags & FloatingWindowFlag::DontUseParentForFloatingWindows) && (m_flags & FloatingWindowFlag::UseQtWindow);
 
  811FloatingWindowFlags FloatingWindow::floatingWindowFlags()
 const 
Application-wide config to tune certain behaviours of the framework.
static FloatingWindowFlags flagsForFloatingWindow(FloatingWindowFlags requestedFlags)
MainWindowBase * actualParent(MainWindowBase *candidate)
static FloatingWindowFlags floatingWindowFlagsForFrame(Frame *frame)
static Qt::WindowFlags windowFlagsToUse(FloatingWindowFlags requestedFlags)
static MainWindowBase * hackFindParentHarder(Frame *frame, MainWindowBase *candidateParent)
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
bool spontaneous() const const
QEvent::Type type() const const
virtual bool event(QEvent *event) override
void destroyed(QObject *obj)
QPoint center() const const
bool intersects(const QRect &rectangle) const const
bool isNull() const const
void moveCenter(const QPoint &position)
void moveTopLeft(const QPoint &position)
void setHeight(int height)
void setSize(const QSize &size)
QPoint topLeft() const const
QSize boundedTo(const QSize &otherSize) const const
bool isEmpty() const const