introduce floating gap window

--this window responsibility is to check
if the mouse is still inside the real floating
gap and in such case to prevent the dock from
hiding
pull/11/head
Michail Vourlakos 5 years ago
parent 35ce0496ec
commit 3f68665300

@ -3,6 +3,7 @@ set(lattedock-app_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/containmentinterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/contextmenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/effects.cpp
${CMAKE_CURRENT_SOURCE_DIR}/floatinggapwindow.cpp
${CMAKE_CURRENT_SOURCE_DIR}/panelshadows.cpp
${CMAKE_CURRENT_SOURCE_DIR}/positioner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/screenedgeghostwindow.cpp

@ -0,0 +1,378 @@
/*
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "floatinggapwindow.h"
// local
#include "view.h"
// Qt
#include <QDebug>
#include <QSurfaceFormat>
#include <QQuickView>
#include <QTimer>
// KDE
#include <KWayland/Client/plasmashell.h>
#include <KWayland/Client/surface.h>
#include <KWindowSystem>
// X11
#include <NETWM>
namespace Latte {
namespace ViewPart {
FloatingGapWindow::FloatingGapWindow(Latte::View *view) :
m_latteView(view)
{
m_corona = qobject_cast<Latte::Corona *>(view->corona());
m_debugMode = (qApp->arguments().contains("-d") && qApp->arguments().contains("--kwinedges"));
if (m_debugMode) {
m_showColor = QColor("green");
m_hideColor = QColor("red");
} else {
m_showColor = QColor(Qt::transparent);
m_hideColor = QColor(Qt::transparent);
m_showColor.setAlpha(0);
m_hideColor.setAlpha(1);
}
setColor(m_showColor);
setDefaultAlphaBuffer(true);
setFlags(Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint
| Qt::NoDropShadowWindowHint
| Qt::WindowDoesNotAcceptFocus);
m_fixGeometryTimer.setSingleShot(true);
m_fixGeometryTimer.setInterval(500);
connect(&m_fixGeometryTimer, &QTimer::timeout, this, &FloatingGapWindow::fixGeometry);
//! this timer is used in order to identify if mouse is still present in sensitive floating
//! areas and in such case to prevent a real-floating view to hide itself
m_asyncMouseTimer.setSingleShot(true);
m_asyncMouseTimer.setInterval(200);
connect(&m_asyncMouseTimer, &QTimer::timeout, this, [this]() {
if (m_inAsyncContainsMouse && !m_containsMouse) {
emit asyncContainsMouseChanged(false);
hideWithMask();
m_inAsyncContainsMouse = false;
}
});
connect(this, &QQuickView::xChanged, this, &FloatingGapWindow::startGeometryTimer);
connect(this, &QQuickView::yChanged, this, &FloatingGapWindow::startGeometryTimer);
connect(this, &QQuickView::widthChanged, this, &FloatingGapWindow::startGeometryTimer);
connect(this, &QQuickView::heightChanged, this, &FloatingGapWindow::startGeometryTimer);
connect(m_latteView, &Latte::View::absoluteGeometryChanged, this, &FloatingGapWindow::updateGeometry);
connect(m_latteView, &Latte::View::screenGeometryChanged, this, &FloatingGapWindow::updateGeometry);
connect(m_latteView, &Latte::View::locationChanged, this, &FloatingGapWindow::updateGeometry);
connect(m_latteView, &QQuickView::screenChanged, this, [this]() {
setScreen(m_latteView->screen());
updateGeometry();
});
if (!KWindowSystem::isPlatformWayland()) {
//! IMPORTANT!!! ::: This fixes a bug when closing an Activity all views from all Activities are
//! disappearing! With this code parts they reappear!!!
m_visibleHackTimer1.setInterval(400);
m_visibleHackTimer2.setInterval(2500);
m_visibleHackTimer1.setSingleShot(true);
m_visibleHackTimer2.setSingleShot(true);
connectionsHack << connect(this, &QWindow::visibleChanged, this, [&]() {
if (!m_inDelete && m_latteView && m_latteView->layout() && !isVisible()) {
m_visibleHackTimer1.start();
m_visibleHackTimer2.start();
} else if (!m_inDelete) {
//! For some reason when the window is hidden in the edge under X11 afterwards
//! is losing its window flags
m_corona->wm()->setViewExtraFlags(this);
}
});
connectionsHack << connect(&m_visibleHackTimer1, &QTimer::timeout, this, [&]() {
if (!m_inDelete && m_latteView && m_latteView->layout() && !isVisible()) {
show();
emit forcedShown();
//qDebug() << "Floating Gap:: Enforce reshow from timer 1...";
} else {
//qDebug() << "Floating Gap:: No needed reshow from timer 1...";
}
});
connectionsHack << connect(&m_visibleHackTimer2, &QTimer::timeout, this, [&]() {
if (!m_inDelete && m_latteView && m_latteView->layout() && !isVisible()) {
show();
emit forcedShown();
//qDebug() << "Floating Gap:: Enforce reshow from timer 2...";
} else {
//qDebug() << "Floating Gap:: No needed reshow from timer 2...";
}
});
connectionsHack << connect(this, &FloatingGapWindow::forcedShown, this, [&]() {
m_corona->wm()->unregisterIgnoredWindow(m_trackedWindowId);
m_trackedWindowId = winId();
m_corona->wm()->registerIgnoredWindow(m_trackedWindowId);
});
}
setupWaylandIntegration();
if (KWindowSystem::isPlatformX11()) {
m_trackedWindowId = winId();
m_corona->wm()->registerIgnoredWindow(m_trackedWindowId);
} else {
connect(m_corona->wm(), &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, [&]() {
if (m_trackedWindowId.isNull()) {
m_trackedWindowId = m_corona->wm()->winIdFor("latte-dock", geometry());
m_corona->wm()->registerIgnoredWindow(m_trackedWindowId);
}
});
}
setScreen(m_latteView->screen());
show();
updateGeometry();
hideWithMask();
}
FloatingGapWindow::~FloatingGapWindow()
{
m_inDelete = true;
m_corona->wm()->unregisterIgnoredWindow(KWindowSystem::isPlatformX11() ? winId() : m_trackedWindowId);
m_latteView = nullptr;
// clear mode
m_visibleHackTimer1.stop();
m_visibleHackTimer2.stop();
for (auto &c : connectionsHack) {
disconnect(c);
}
if (m_shellSurface) {
delete m_shellSurface;
}
}
int FloatingGapWindow::location()
{
return (int)m_latteView->location();
}
int FloatingGapWindow::thickness() const
{
return m_thickness;
}
Latte::View *FloatingGapWindow::parentView()
{
return m_latteView;
}
KWayland::Client::PlasmaShellSurface *FloatingGapWindow::surface()
{
return m_shellSurface;
}
void FloatingGapWindow::updateGeometry()
{
if (m_latteView->positioner()->slideOffset() != 0) {
return;
}
QRect newGeometry;
m_thickness = m_latteView->screenEdgeMargin();
int length = m_latteView->formFactor() == Plasma::Types::Horizontal ? m_latteView->absoluteGeometry().width() : m_latteView->absoluteGeometry().height();
if (m_latteView->location() == Plasma::Types::BottomEdge) {
int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left());
newGeometry.setX(xF);
newGeometry.setY(m_latteView->screenGeometry().bottom() - m_thickness);
} else if (m_latteView->location() == Plasma::Types::TopEdge) {
int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left());
newGeometry.setX(xF);
newGeometry.setY(m_latteView->screenGeometry().top());
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top());
newGeometry.setX(m_latteView->screenGeometry().left());
newGeometry.setY(yF);
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top());
newGeometry.setX(m_latteView->screenGeometry().right() - m_thickness);
newGeometry.setY(yF);
}
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
newGeometry.setWidth(length);
newGeometry.setHeight(m_thickness + 1);
} else {
newGeometry.setWidth(m_thickness + 1);
newGeometry.setHeight(length);
}
m_calculatedGeometry = newGeometry;
fixGeometry();
}
void FloatingGapWindow::fixGeometry()
{
if (!m_calculatedGeometry.isEmpty()
&& (m_calculatedGeometry.x() != x() || m_calculatedGeometry.y() != y()
|| m_calculatedGeometry.width() != width() || m_calculatedGeometry.height() != height())) {
setMinimumSize(m_calculatedGeometry.size());
setMaximumSize(m_calculatedGeometry.size());
resize(m_calculatedGeometry.size());
setPosition(m_calculatedGeometry.x(), m_calculatedGeometry.y());
if (m_shellSurface) {
m_shellSurface->setPosition(m_calculatedGeometry.topLeft());
}
}
}
void FloatingGapWindow::startGeometryTimer()
{
m_fixGeometryTimer.start();
}
void FloatingGapWindow::setupWaylandIntegration()
{
if (m_shellSurface || !KWindowSystem::isPlatformWayland() || !m_latteView || !m_latteView->containment()) {
// already setup
return;
}
if (m_corona) {
using namespace KWayland::Client;
PlasmaShell *interface = m_corona->waylandCoronaInterface();
if (!interface) {
return;
}
Surface *s = Surface::fromWindow(this);
if (!s) {
return;
}
qDebug() << "wayland screen edge ghost window surface was created...";
m_shellSurface = interface->createSurface(s, this);
m_corona->wm()->setViewExtraFlags(m_shellSurface);
m_shellSurface->setPanelTakesFocus(false);
}
}
bool FloatingGapWindow::containsMouse() const
{
return m_containsMouse;
}
void FloatingGapWindow::setContainsMouse(bool contains)
{
if (m_containsMouse == contains) {
return;
}
m_containsMouse = contains;
}
bool FloatingGapWindow::event(QEvent *e)
{
if (e->type() == QEvent::DragEnter || e->type() == QEvent::DragMove) {
setContainsMouse(true);
emit dragEntered();
} else if (e->type() == QEvent::Enter) {
setContainsMouse(true);
triggerAsyncContainsMouseSignals();
} else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave) {
setContainsMouse(false);
if (m_inAsyncContainsMouse) {
m_asyncMouseTimer.stop();
m_inAsyncContainsMouse = false;
emit asyncContainsMouseChanged(true);
}
} else if (e->type() == QEvent::Show) {
m_corona->wm()->setViewExtraFlags(this);
}
return QQuickView::event(e);
}
void FloatingGapWindow::callAsyncContainsMouse()
{
m_inAsyncContainsMouse = true;
m_asyncMouseTimer.start();
showWithMask();
}
void FloatingGapWindow::triggerAsyncContainsMouseSignals()
{
if (!m_inAsyncContainsMouse) {
return;
}
//! this function is called QEvent::Enter
m_asyncMouseTimer.stop();
hideWithMask();
}
void FloatingGapWindow::hideWithMask()
{
if (m_debugMode) {
qDebug() << " Floating Gap Window :: MASK HIDE...";
}
//! old values: 0,0,1,1 were blocking the top-left corner of the window
QRect maskGeometry{-2, 0, 1, 1};
setMask(maskGeometry);
//! repaint in order to update mask immediately
setColor(m_hideColor);
}
void FloatingGapWindow::showWithMask()
{
if (m_debugMode) {
qDebug() << " Floating Gap Window :: MAKS SHOW...";
}
setMask(QRegion());
//! repaint in order to update mask immediately
setColor(m_showColor);
}
}
}

@ -0,0 +1,139 @@
/*
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FLOATINGGAPWINDOW_H
#define FLOATINGWINDOW_H
// local
#include "../lattecorona.h"
#include "../wm/windowinfowrap.h"
// Qt
#include <QObject>
#include <QQuickView>
#include <QTimer>
namespace KWayland {
namespace Client {
class PlasmaShellSurface;
}
}
namespace Latte {
class Corona;
class View;
}
namespace Latte {
namespace ViewPart {
//! What is the importance of this class?
//!
//! This window is responsible to identify if the mouse is still present
//! in the REAL FLOATING GAP between the VIEW and the SCREEN EDGE.
//! When VIEWS are REAL FLOATING then the VIEW Window is really placed
//! as it is shown to the user. In that case we need a way to check
//! where the mouse is even though it is OUTSIDE the VIEW or the
//! SCREENEDGEGHOSTWINDOW. The main functionality of FloatingGapWindow
//! is that it is TEMPORARILY shown/draw after a MUSTHIDE signal of
//! VisibilityManager was sent; in order to check if the mouse is still
//! inside the FLOATINGGAP. After it has really identified where mouse
//! is present, an FloatingGapWindow::asyncContainsMouse(contains) signal
//! is sent.
class FloatingGapWindow : public QQuickView
{
Q_OBJECT
public:
FloatingGapWindow(Latte::View *view);
~FloatingGapWindow() override;
int location();
int thickness() const;
void hideWithMask();
void showWithMask();
Latte::View *parentView();
KWayland::Client::PlasmaShellSurface *surface();
void callAsyncContainsMouse();
signals:
void asyncContainsMouseChanged(bool contains); //called from visibility to check if mouse is in the free sensitive floating area
void dragEntered();
void forcedShown(); //[workaround] forced shown to avoid a KWin issue that hides windows when activities are stopped
protected:
bool event(QEvent *ev) override;
private slots:
void startGeometryTimer();
void updateGeometry();
void fixGeometry();
private:
bool containsMouse() const;
void setContainsMouse(bool contains);
void setupWaylandIntegration();
void triggerAsyncContainsMouseSignals();
private:
bool m_debugMode{false};
bool m_containsMouse{false};
bool m_inDelete{false};
bool m_inAsyncContainsMouse{false}; //called from visibility to check if mouse is in the free sensitive floating area
int m_thickness{2};
QRect m_calculatedGeometry;
//! [workaround] colors in order to help masking to apply immediately
//! for some reason when the window in with no content the mask is not
//! update immediately
QColor m_hideColor;
QColor m_showColor;
QTimer m_asyncMouseTimer; //called from visibility to check if mouse is in the free sensitive floating area
QTimer m_fixGeometryTimer;
//! HACK: Timers in order to handle KWin faulty
//! behavior that hides Views when closing Activities
//! with no actual reason
QTimer m_visibleHackTimer1;
QTimer m_visibleHackTimer2;
//! Connections for the KWin visibility hack
QList<QMetaObject::Connection> connectionsHack;
Latte::View *m_latteView{nullptr};
QPointer<Latte::Corona> m_corona;
Latte::WindowSystem::WindowId m_trackedWindowId;
KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr};
};
}
}
#endif

@ -197,10 +197,7 @@ void ScreenEdgeGhostWindow::updateGeometry()
QRect newGeometry;
if (m_latteView->screenEdgeMargin()>0 && m_latteView->behaveAsPlasmaPanel()) {
//real floating
m_thickness = m_latteView->screenEdgeMargin();
} else if (KWindowSystem::compositingActive()) {
if (KWindowSystem::compositingActive()) {
m_thickness = 6;
} else {
m_thickness = 2;

@ -480,6 +480,18 @@ void View::updateAbsoluteGeometry(bool bypassChecks)
QRect absGeometry {x() + m_localGeometry.x(), y() + m_localGeometry.y()
, m_localGeometry.width(), m_localGeometry.height()};
if (isFloatingWindow()) {
if (location() == Plasma::Types::BottomEdge) {
absGeometry.setY(screenGeometry().bottom() - m_screenEdgeMargin - m_normalThickness);
} else if (location() == Plasma::Types::TopEdge) {
absGeometry.setY(screenGeometry().top() + m_screenEdgeMargin);
} else if (location() == Plasma::Types::LeftEdge) {
absGeometry.setX(screenGeometry().left() + m_screenEdgeMargin);
} else if (location() == Plasma::Types::RightEdge) {
absGeometry.setX(screenGeometry().right() - m_screenEdgeMargin - m_normalThickness);
}
}
if (m_absoluteGeometry == absGeometry && !bypassChecks) {
return;
}

@ -22,6 +22,7 @@
// local
#include "positioner.h"
#include "floatinggapwindow.h"
#include "screenedgeghostwindow.h"
#include "view.h"
#include "windowstracker/currentscreentracker.h"
@ -58,25 +59,11 @@ VisibilityManager::VisibilityManager(PlasmaQuick::ContainmentView *view)
m_wm = m_corona->wm();
connect(this, &VisibilityManager::slideOutFinished, this, &VisibilityManager::updateHiddenState);
connect(this, &VisibilityManager::slideInFinished, this, [&]() {
if (m_latteView && !m_latteView->screenEdgeMarginEnabled()) {
//! after slide-out the real floating windows should ignore their criteria
//! until containsMouse from view has been set to true and false to afterwards
updateHiddenState();
} else {
m_timerHide.stop();
}
});
connect(this, &VisibilityManager::slideInFinished, this, &VisibilityManager::updateHiddenState);
connect(this, &VisibilityManager::enableKWinEdgesChanged, this, &VisibilityManager::updateKWinEdgesSupport);
connect(this, &VisibilityManager::modeChanged, this, &VisibilityManager::updateKWinEdgesSupport);
connect(this, &VisibilityManager::mustBeHide, this, [&]() {
if (supportsKWinEdges() && m_latteView->screenEdgeMargin()>0 && m_latteView->behaveAsPlasmaPanel()) {
m_edgeGhostWindow->showWithMask();
}
});
if (m_latteView) {
connect(m_latteView, &Latte::View::eventTriggered, this, &VisibilityManager::viewEventManager);
connect(m_latteView, &Latte::View::byPassWMChanged, this, &VisibilityManager::updateKWinEdgesSupport);
@ -107,8 +94,13 @@ VisibilityManager::VisibilityManager(PlasmaQuick::ContainmentView *view)
});
connect(&m_timerHide, &QTimer::timeout, this, [&]() {
if (!m_blockHiding && !m_isHidden && !m_isBelowLayer && !m_dragEnter) {
// qDebug() << "must be hide";
emit mustBeHide();
if (m_latteView->isFloatingWindow()) {
//! first check if mouse is inside the floating gap
checkMouseInFloatingArea();
} else {
//! immediate call
emit mustBeHide();
}
}
});
@ -123,6 +115,10 @@ VisibilityManager::~VisibilityManager()
if (m_edgeGhostWindow) {
m_edgeGhostWindow->deleteLater();
}
if (m_floatingGapWindow) {
m_floatingGapWindow->deleteLater();
}
}
Types::Visibility VisibilityManager::mode() const
@ -491,13 +487,7 @@ void VisibilityManager::updateGhostWindowState()
if (m_mode == Latte::Types::WindowsCanCover) {
m_wm->setActiveEdge(m_edgeGhostWindow, m_isBelowLayer && !m_containsMouse);
} else {
/* bool viewIsFloatingAndContainsMouse =
m_latteView->behaveAsPlasmaPanel()
&& m_latteView->screenEdgeMarginEnabled()
&& m_latteView->screenEdgeMargin()>0
&& (m_edgeGhostWindow->containsMouse() || m_containsMouse);*/
bool activated = (m_isHidden && !m_containsMouse && !m_edgeGhostWindow->containsMouse());
bool activated = (m_isHidden && !windowContainsMouse());
m_wm->setActiveEdge(m_edgeGhostWindow, activated);
}
@ -572,7 +562,7 @@ void VisibilityManager::updateHiddenState()
switch (m_mode) {
case Types::AutoHide:
case Types::WindowsCanCover:
raiseView(m_containsMouse || (m_edgeGhostWindow && m_edgeGhostWindow->containsMouse()));
raiseView(m_containsMouse);
break;
case Types::DodgeActive:
@ -597,6 +587,10 @@ void VisibilityManager::applyActivitiesToHiddenWindows(const QStringList &activi
if (m_edgeGhostWindow) {
m_wm->setWindowOnActivities(*m_edgeGhostWindow, activities);
}
if (m_floatingGapWindow) {
m_wm->setWindowOnActivities(*m_floatingGapWindow, activities);
}
}
void VisibilityManager::dodgeActive()
@ -634,6 +628,7 @@ void VisibilityManager::dodgeAllWindows()
if (m_containsMouse) {
raiseView(true);
return;
}
bool windowIntersects{m_latteView->windowsTracker()->currentScreen()->activeWindowTouching() || m_latteView->windowsTracker()->currentScreen()->existsWindowTouching()};
@ -720,9 +715,17 @@ void VisibilityManager::setContainsMouse(bool contains)
m_containsMouse = contains;
emit containsMouseChanged();
}
if (contains && m_mode != Types::AlwaysVisible) {
raiseView(true);
bool VisibilityManager::windowContainsMouse()
{
return m_containsMouse || (m_edgeGhostWindow && m_edgeGhostWindow->containsMouse());
}
void VisibilityManager::checkMouseInFloatingArea()
{
if (m_floatingGapWindow && m_latteView->isFloatingWindow()) {
m_floatingGapWindow->callAsyncContainsMouse();
}
}
@ -785,14 +788,19 @@ void VisibilityManager::updateKWinEdgesSupport()
if (m_enableKWinEdgesFromUser) {
createEdgeGhostWindow();
if (m_latteView->isFloatingWindow()) {
createFloatingGapWindow();
}
} else if (!m_enableKWinEdgesFromUser) {
deleteEdgeGhostWindow();
deleteFloatingGapWindow();
}
} else if (m_mode == Types::WindowsCanCover) {
createEdgeGhostWindow();
} else {
deleteEdgeGhostWindow();
deleteFloatingGapWindow();
}
}
@ -801,23 +809,12 @@ void VisibilityManager::createEdgeGhostWindow()
if (!m_edgeGhostWindow) {
m_edgeGhostWindow = new ScreenEdgeGhostWindow(m_latteView);
connect(m_edgeGhostWindow, &ScreenEdgeGhostWindow::containsMouseChanged, this, [ = ](bool contains) {
connect(m_edgeGhostWindow, &ScreenEdgeGhostWindow::containsMouseChanged, this, [ = ](bool contains) {
if (contains) {
if (!m_isHidden) {
//! immediate call
m_edgeGhostWindow->hideWithMask();
emit mustBeShown();
} else {
raiseView(true);
}
raiseView(true);
} else {
if (!m_isHidden) {
//! immediate call
updateHiddenState();
} else {
m_timerShow.stop();
updateGhostWindowState();
}
m_timerShow.stop();
updateGhostWindowState();
}
});
@ -861,6 +858,41 @@ void VisibilityManager::deleteEdgeGhostWindow()
}
}
void VisibilityManager::createFloatingGapWindow()
{
if (!m_floatingGapWindow) {
m_floatingGapWindow = new FloatingGapWindow(m_latteView);
connect(m_floatingGapWindow, &FloatingGapWindow::asyncContainsMouseChanged, this, [ = ](bool contains) {
if (contains) {
if (m_latteView->isFloatingWindow() && !m_isHidden) {
//! immediate call after contains mouse checks for mouse in sensitive floating areas
updateHiddenState();
}
} else {
if (m_latteView->isFloatingWindow() && !m_isHidden) {
//! immediate call after contains mouse checks for mouse in sensitive floating areas
emit mustBeHide();
}
}
});
}
}
void VisibilityManager::deleteFloatingGapWindow()
{
if (m_floatingGapWindow) {
m_floatingGapWindow->deleteLater();
m_floatingGapWindow = nullptr;
}
}
bool VisibilityManager::supportsFloatingGap() const
{
return (m_floatingGapWindow != nullptr);
}
//! END: VisibilityManager implementation
}

@ -38,6 +38,7 @@ namespace Latte {
class Corona;
class View;
namespace ViewPart {
class FloatingGapWindow;
class ScreenEdgeGhostWindow;
}
namespace WindowSystem {
@ -154,9 +155,18 @@ private:
void deleteEdgeGhostWindow();
void updateGhostWindowState();
//! Floating Gap Support functions
void createFloatingGapWindow();
void deleteFloatingGapWindow();
bool supportsFloatingGap() const;
void updateStrutsBasedOnLayoutsAndActivities(bool forceUpdate = false);
void viewEventManager(QEvent *ev);
void checkMouseInFloatingArea();
bool windowContainsMouse();
QRect acceptableStruts();
private slots:
@ -191,6 +201,9 @@ private:
std::array<QMetaObject::Connection, 1> m_connectionsKWinEdges;
ScreenEdgeGhostWindow *m_edgeGhostWindow{nullptr};
//! Floating Gap
FloatingGapWindow *m_floatingGapWindow{nullptr};
Latte::Corona *m_corona{nullptr};
Latte::View *m_latteView{nullptr};

Loading…
Cancel
Save