Always outter indicators if the center is obscured with something else

If there's some other floating window over our drop zone, then it's
very difficult to drop if there's no outter indicators.

Now we'll show the outter indicators if we suspect there's some other
window obscuring
This commit is contained in:
Sergio Martins
2020-09-16 12:36:47 +01:00
parent 74adb5f021
commit 576627eb17
5 changed files with 54 additions and 1 deletions

View File

@@ -15,6 +15,7 @@
#include "Position_p.h" #include "Position_p.h"
#include "MultiSplitter_p.h" #include "MultiSplitter_p.h"
#include "QWidgetAdapter.h" #include "QWidgetAdapter.h"
#include "Config.h"
#include <QPointer> #include <QPointer>
#include <QDebug> #include <QDebug>
@@ -152,6 +153,38 @@ QStringList DockRegistry::dockWidgetNames() const
return names; return names;
} }
bool DockRegistry::isProbablyObscured(QWindow *window, FloatingWindow *exclude) const
{
if (!window)
return false;
const QRect geo = window->geometry();
for (FloatingWindow *fw : m_nestedWindows) {
QWindow *fwWindow = fw->QWidgetAdapter::windowHandle();
if (fw == exclude || fwWindow == window)
continue;
if (fwWindow->geometry().intersects(geo)) {
// fw might be bellow, but we don't have a way to check. So be conservative and return true.
return true;
}
}
// Floating windows are Tool (keep above), unless we disabled it in Config
const bool targetIsToolWindow = !(Config::self().flags() & Config::Flag_DontUseUtilityFloatingWindows) && floatingWindowForHandle(window) != nullptr;
for (MainWindowBase *mw : m_mainWindows) {
QWindow *mwWindow = mw->window()->windowHandle();
if (mwWindow != window && !targetIsToolWindow && mwWindow->geometry().intersects(geo)) {
// Two main windows that intersect. Return true. If the target is a tool window it will be above, so we don't care.
return true;
}
}
return false;
}
MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const
{ {
MainWindowBase::List result; MainWindowBase::List result;

View File

@@ -165,6 +165,13 @@ public:
/// @brief Returns a list of all known dock widget unique names /// @brief Returns a list of all known dock widget unique names
QStringList dockWidgetNames() const; QStringList dockWidgetNames() const;
/// @brief returns if the specified window has some other window on top (with higher Z)
/// This is an approximation, as we don't have ways to compare Z, so we mostly intersect
/// geometries.
/// @param target The window which we want to know if it's probably obscured
/// @param exclude This window should not be counted as an obscurer. (It's being dragged).
bool isProbablyObscured(QWindow *target, FloatingWindow *exclude) const;
protected: protected:
bool eventFilter(QObject *watched, QEvent *event) override; bool eventFilter(QObject *watched, QEvent *event) override;
private: private:

View File

@@ -337,6 +337,12 @@ void DragController::releaseMouse(QWidgetOrQuick *target)
} }
} }
FloatingWindow *DragController::windowBeingDragged() const
{
return m_windowBeingDragged ? m_windowBeingDragged->floatingWindow()
: nullptr;
}
static QMouseEvent *mouseEvent(QEvent *e) static QMouseEvent *mouseEvent(QEvent *e)
{ {
switch (e->type()) { switch (e->type()) {

View File

@@ -50,6 +50,8 @@ public:
void grabMouseFor(QWidgetOrQuick *); void grabMouseFor(QWidgetOrQuick *);
void releaseMouse(QWidgetOrQuick *); void releaseMouse(QWidgetOrQuick *);
FloatingWindow *windowBeingDragged() const;
Q_SIGNALS: Q_SIGNALS:
void mousePressed(); void mousePressed();
void manhattanLengthMove(); void manhattanLengthMove();

View File

@@ -15,6 +15,7 @@
#include "Frame_p.h" #include "Frame_p.h"
#include "Logging_p.h" #include "Logging_p.h"
#include "Config.h" #include "Config.h"
#include "DockRegistry_p.h"
#include "FrameworkWidgetFactory.h" #include "FrameworkWidgetFactory.h"
#include "ClassicIndicatorsWindow_p.h" #include "ClassicIndicatorsWindow_p.h"
@@ -86,7 +87,11 @@ void ClassicIndicators::updateIndicatorsVisibility(bool visible)
const bool isTheOnlyFrame = hoveredFrame && hoveredFrame->isTheOnlyFrame(); const bool isTheOnlyFrame = hoveredFrame && hoveredFrame->isTheOnlyFrame();
m_innerIndicatorsVisible = visible && hoveredFrame; m_innerIndicatorsVisible = visible && hoveredFrame;
m_outterIndicatorsVisible = visible && !isTheOnlyFrame;
// If there's only 1 frame in the layout, the outter indicators are redundant, as they do the same thing as the internal ones.
// But there might be another window obscuring our target, so it's useful to show the outter indicators in this case
m_outterIndicatorsVisible = visible && (!isTheOnlyFrame ||
DockRegistry::self()->isProbablyObscured(hoveredFrame->window()->windowHandle(), DragController::instance()->windowBeingDragged()));
Q_EMIT innerIndicatorsVisibleChanged(); Q_EMIT innerIndicatorsVisibleChanged();
Q_EMIT outterIndicatorsVisibleChanged(); Q_EMIT outterIndicatorsVisibleChanged();