Commit d25c4652 authored by Martin Flöser's avatar Martin Flöser

Move layer functionality to AbstractClient

Merges together the code from ShellClient and Client and removes the
starting differences. Long term it's better to have only one
implementation to prevent diversions in the implementation.

As it doesn't match exactly protected virtual methods are called
which allow more specific implementations for a certain aspect of the
layer resolving.
parent 49e5e819
......@@ -189,8 +189,17 @@ void AbstractClient::doSetActive()
{
}
Layer AbstractClient::layer() const
{
if (m_layer == UnknownLayer)
const_cast< AbstractClient* >(this)->m_layer = belongsToLayer();
return m_layer;
}
void AbstractClient::updateLayer()
{
if (layer() == belongsToLayer())
return;
StackingUpdatesBlocker blocker(workspace());
invalidateLayer(); // invalidate, will be updated when doing restacking
for (auto it = transients().constBegin(),
......@@ -200,6 +209,57 @@ void AbstractClient::updateLayer()
void AbstractClient::invalidateLayer()
{
m_layer = UnknownLayer;
}
Layer AbstractClient::belongsToLayer() const
{
// NOTICE while showingDesktop, desktops move to the AboveLayer
// (interchangeable w/ eg. yakuake etc. which will at first remain visible)
// and the docks move into the NotificationLayer (which is between Above- and
// ActiveLayer, so that active fullscreen windows will still cover everything)
// Since the desktop is also activated, nothing should be in the ActiveLayer, though
if (isDesktop())
return workspace()->showingDesktop() ? AboveLayer : DesktopLayer;
if (isSplash()) // no damn annoying splashscreens
return NormalLayer; // getting in the way of everything else
if (isDock()) {
if (workspace()->showingDesktop())
return NotificationLayer;
return layerForDock();
}
if (isOnScreenDisplay())
return OnScreenDisplayLayer;
if (isNotification())
return NotificationLayer;
if (workspace()->showingDesktop() && belongsToDesktop()) {
return AboveLayer;
}
if (keepBelow())
return BelowLayer;
if (isActiveFullScreen())
return ActiveLayer;
if (keepAbove())
return AboveLayer;
return NormalLayer;
}
bool AbstractClient::belongsToDesktop() const
{
return false;
}
Layer AbstractClient::layerForDock() const
{
// slight hack for the 'allow window to cover panel' Kicker setting
// don't move keepbelow docks below normal window, but only to the same
// layer, so that both may be raised to cover the other
if (keepBelow())
return NormalLayer;
if (keepAbove()) // slight hack for the autohiding panels
return AboveLayer;
return DockLayer;
}
void AbstractClient::setKeepAbove(bool b)
......@@ -909,4 +969,16 @@ void AbstractClient::removeTransientFromList(AbstractClient *cl)
m_transients.removeAll(cl);
}
bool AbstractClient::isActiveFullScreen() const
{
if (!isFullScreen())
return false;
const auto ac = workspace()->mostRecentlyActivatedClient(); // instead of activeClient() - avoids flicker
// according to NETWM spec implementation notes suggests
// "focused windows having state _NET_WM_STATE_FULLSCREEN" to be on the highest layer.
// we'll also take the screen into account
return ac && (ac == this || ac->screen() != screen());
}
}
......@@ -384,7 +384,8 @@ public:
* @param mode The tile mode (left/right) to give this window.
*/
virtual void setQuickTileMode(QuickTileMode mode, bool keyboard = false) = 0;
virtual void updateLayer();
Layer layer() const override;
void updateLayer();
enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet };
virtual void move(int x, int y, ForceGeometry_t force = NormalGeometrySet) = 0;
......@@ -505,7 +506,11 @@ protected:
**/
void removeTransientFromList(AbstractClient* cl);
virtual void invalidateLayer();
Layer belongsToLayer() const;
virtual bool belongsToDesktop() const;
void invalidateLayer();
virtual bool isActiveFullScreen() const;
virtual Layer layerForDock() const;
private:
void handlePaletteChange();
......@@ -537,6 +542,7 @@ private:
AbstractClient *m_transientFor = nullptr;
QList<AbstractClient*> m_transients;
bool m_modal = false;
Layer m_layer = UnknownLayer;
};
inline void AbstractClient::move(const QPoint& p, ForceGeometry_t force)
......
......@@ -116,7 +116,6 @@ Client::Client()
, m_colormap(XCB_COLORMAP_NONE)
, in_group(NULL)
, tab_group(NULL)
, in_layer(UnknownLayer)
, ping_timer(NULL)
, m_killHelperPID(0)
, m_pingTimestamp(XCB_TIME_CURRENT_TIME)
......
......@@ -251,7 +251,6 @@ public:
bool isFullScreen() const override;
bool isFullScreenable() const override;
bool isFullScreenable(bool fullscreen_hack) const;
bool isActiveFullScreen() const;
bool userCanSetFullScreen() const override;
QRect geometryFSRestore() const {
return geom_fs_restore; // Only for session saving
......@@ -265,9 +264,6 @@ public:
bool userCanSetNoBorder() const override;
void checkNoBorder();
virtual Layer layer() const;
Layer belongsToLayer() const;
void updateLayer() override;
int sessionStackingOrder() const;
// Auxiliary functions, depend on the windowType
......@@ -520,7 +516,8 @@ protected:
void doMinimize() override;
void doSetSkipPager() override;
void doSetSkipTaskbar() override;
void invalidateLayer() override;
bool belongsToDesktop() const override;
bool isActiveFullScreen() const override;
private Q_SLOTS:
void delayedSetShortcut();
......@@ -734,7 +731,6 @@ private:
QString cap_normal, cap_iconic, cap_suffix, cap_deco;
Group* in_group;
TabGroup* tab_group;
Layer in_layer;
QTimer* ping_timer;
qint64 m_killHelperPID;
xcb_timestamp_t m_pingTimestamp;
......@@ -894,11 +890,6 @@ inline xcb_colormap_t Client::colormap() const
return m_colormap;
}
inline void Client::invalidateLayer()
{
in_layer = UnknownLayer;
}
inline int Client::sessionStackingOrder() const
{
return sm_stacking_order;
......
......@@ -820,61 +820,13 @@ void Client::doSetKeepBelow()
tabGroup()->updateStates(this, TabGroup::Layer);
}
Layer Client::layer() const
bool Client::belongsToDesktop() const
{
if (in_layer == UnknownLayer)
const_cast< Client* >(this)->in_layer = belongsToLayer();
return in_layer;
}
Layer Client::belongsToLayer() const
{
// NOTICE while showingDesktop, desktops move to the AboveLayer
// (interchangeable w/ eg. yakuake etc. which will at first remain visible)
// and the docks move into the NotificationLayer (which is between Above- and
// ActiveLayer, so that active fullscreen windows will still cover everything)
// Since the desktop is also activated, nothing should be in the ActiveLayer, though
if (isDesktop())
return workspace()->showingDesktop() ? AboveLayer : DesktopLayer;
if (isSplash()) // no damn annoying splashscreens
return NormalLayer; // getting in the way of everything else
if (isDock()) {
if (workspace()->showingDesktop())
return NotificationLayer;
// slight hack for the 'allow window to cover panel' Kicker setting
// don't move keepbelow docks below normal window, but only to the same
// layer, so that both may be raised to cover the other
if (keepBelow())
return NormalLayer;
if (keepAbove()) // slight hack for the autohiding panels
return AboveLayer;
return DockLayer;
}
if (isOnScreenDisplay())
return OnScreenDisplayLayer;
if (isNotification())
return NotificationLayer;
if (workspace()->showingDesktop()) {
foreach (const Client *c, group()->members()) {
if (c->isDesktop())
return AboveLayer;
}
foreach (const Client *c, group()->members()) {
if (c->isDesktop())
return true;
}
if (keepBelow())
return BelowLayer;
if (isActiveFullScreen())
return ActiveLayer;
if (keepAbove())
return AboveLayer;
return NormalLayer;
}
void Client::updateLayer()
{
if (layer() == belongsToLayer())
return;
AbstractClient::updateLayer();
return false;
}
bool rec_checkTransientOnTop(const QList<AbstractClient*> &transients, const Client *topmost)
......@@ -889,6 +841,9 @@ bool rec_checkTransientOnTop(const QList<AbstractClient*> &transients, const Cli
bool Client::isActiveFullScreen() const
{
if (AbstractClient::isActiveFullScreen()) {
return true;
}
if (!isFullScreen())
return false;
......@@ -896,7 +851,7 @@ bool Client::isActiveFullScreen() const
// according to NETWM spec implementation notes suggests
// "focused windows having state _NET_WM_STATE_FULLSCREEN" to be on the highest layer.
// we'll also take the screen into account
return ac && (ac == this || this->group() == ac->group() || ac->screen() != screen());
return ac && (this->group() == ac->group());
}
} // namespace
......@@ -148,42 +148,23 @@ void ShellClient::debug(QDebug &stream) const
Q_UNUSED(stream)
}
Layer ShellClient::layer() const
{
// TODO: implement the rest
if (isDesktop())
return workspace()->showingDesktop() ? AboveLayer : DesktopLayer;
if (isDock()) {
if (workspace()->showingDesktop())
return NotificationLayer;
if (m_plasmaShellSurface) {
switch (m_plasmaShellSurface->panelBehavior()) {
case PlasmaShellSurfaceInterface::PanelBehavior::WindowsCanCover:
return NormalLayer;
case PlasmaShellSurfaceInterface::PanelBehavior::AutoHide:
return AboveLayer;
case PlasmaShellSurfaceInterface::PanelBehavior::WindowsGoBelow:
case PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible:
return DockLayer;
default:
Q_UNREACHABLE();
break;
}
}
// slight hack for the 'allow window to cover panel' Kicker setting
// don't move keepbelow docks below normal window, but only to the same
// layer, so that both may be raised to cover the other
if (keepBelow())
Layer ShellClient::layerForDock() const
{
if (m_plasmaShellSurface) {
switch (m_plasmaShellSurface->panelBehavior()) {
case PlasmaShellSurfaceInterface::PanelBehavior::WindowsCanCover:
return NormalLayer;
if (keepAbove()) // slight hack for the autohiding panels
case PlasmaShellSurfaceInterface::PanelBehavior::AutoHide:
return AboveLayer;
return DockLayer;
case PlasmaShellSurfaceInterface::PanelBehavior::WindowsGoBelow:
case PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible:
return DockLayer;
default:
Q_UNREACHABLE();
break;
}
}
if (isOnScreenDisplay())
return OnScreenDisplayLayer;
if (isFullScreen() && isActive())
return ActiveLayer;
return KWin::NormalLayer;
return AbstractClient::layerForDock();
}
bool ShellClient::shouldUnredirect() const
......
......@@ -45,7 +45,6 @@ public:
QStringList activities() const override;
QPoint clientPos() const override;
QSize clientSize() const override;
Layer layer() const override;
QRect transparentRect() const override;
bool shouldUnredirect() const override;
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
......@@ -119,6 +118,7 @@ protected:
void addDamage(const QRegion &damage) override;
bool belongsToSameApplication(const AbstractClient *other, bool active_hack) const override;
void doSetActive() override;
Layer layerForDock() const override;
private Q_SLOTS:
void clientFullScreenChanged(bool fullScreen);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment