Introduce layer window rule
The new window rule allows to overwrite the stack layer. It can be useful on wayland to force picture-in-picture surfaces (which are xdg-toplevels at the moment) to be placed above fullscreen windows. Keep above flag is unsuitable because fullscreen windows are placed higher "above" windows. CCBUG: 466016
This commit is contained in:
parent
74a193d383
commit
5c4acbdddd
9 changed files with 107 additions and 4 deletions
|
@ -140,6 +140,7 @@ void TestDbusInterface::testGetWindowInfoXdgShellClient()
|
|||
#if KWIN_BUILD_ACTIVITIES
|
||||
{QStringLiteral("activities"), QStringList()},
|
||||
#endif
|
||||
{QStringLiteral("layer"), NormalLayer},
|
||||
};
|
||||
|
||||
// let's get the window info
|
||||
|
@ -276,6 +277,7 @@ void TestDbusInterface::testGetWindowInfoX11Client()
|
|||
#if KWIN_BUILD_ACTIVITIES
|
||||
{QStringLiteral("activities"), QStringList()},
|
||||
#endif
|
||||
{QStringLiteral("layer"), NormalLayer},
|
||||
};
|
||||
|
||||
// let's get the window info
|
||||
|
|
|
@ -151,6 +151,10 @@ private Q_SLOTS:
|
|||
void testScreenApplyNow();
|
||||
void testScreenForceTemporarily();
|
||||
|
||||
void testLayerDontAffect();
|
||||
void testLayerForce();
|
||||
void testLayerForceTemporarily();
|
||||
|
||||
void testMatchAfterNameChange();
|
||||
|
||||
private:
|
||||
|
@ -2980,5 +2984,42 @@ void TestXdgShellWindowRules::testMatchAfterNameChange()
|
|||
QCOMPARE(window->keepAbove(), true);
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testLayerDontAffect()
|
||||
{
|
||||
setWindowRule("layer", QStringLiteral("overlay"), int(Rules::DontAffect));
|
||||
|
||||
createTestWindow();
|
||||
|
||||
// The layer should not be affected by the rule.
|
||||
QCOMPARE(m_window->layer(), NormalLayer);
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testLayerForce()
|
||||
{
|
||||
setWindowRule("layer", QStringLiteral("overlay"), int(Rules::Force));
|
||||
|
||||
createTestWindow();
|
||||
QCOMPARE(m_window->layer(), UnmanagedLayer);
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testLayerForceTemporarily()
|
||||
{
|
||||
setWindowRule("layer", QStringLiteral("overlay"), int(Rules::ForceTemporarily));
|
||||
|
||||
createTestWindow();
|
||||
QCOMPARE(m_window->layer(), UnmanagedLayer);
|
||||
|
||||
// The rule should be discarded when the window is closed.
|
||||
destroyTestWindow();
|
||||
createTestWindow();
|
||||
QCOMPARE(m_window->layer(), NormalLayer);
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestXdgShellWindowRules)
|
||||
#include "xdgshellwindow_rules_test.moc"
|
||||
|
|
|
@ -180,6 +180,7 @@ QVariantMap clientToVariantMap(const Window *c)
|
|||
#if KWIN_BUILD_ACTIVITIES
|
||||
{QStringLiteral("activities"), c->activities()},
|
||||
#endif
|
||||
{QStringLiteral("layer"), c->layer()},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -719,6 +719,12 @@ void RulesModel::populateRuleList()
|
|||
RulePolicy::ForceRule, RuleItem::Boolean,
|
||||
i18n("Block compositing"), i18n("Appearance & Fixes"),
|
||||
QIcon::fromTheme("composite-track-on")));
|
||||
|
||||
auto layer = addRule(new RuleItem(QLatin1String("layer"),
|
||||
RulePolicy::ForceRule, RuleItem::Option,
|
||||
i18n("Layer"), i18n("Appearance & Fixes"),
|
||||
QIcon::fromTheme("view-sort")));
|
||||
layer->setOptionsData(layerModelData());
|
||||
}
|
||||
|
||||
const QHash<QString, QString> RulesModel::x11PropertyHash()
|
||||
|
@ -741,6 +747,7 @@ const QHash<QString, QString> RulesModel::x11PropertyHash()
|
|||
{"type", "type"},
|
||||
{"desktopFile", "desktopfile"},
|
||||
{"desktops", "desktops"},
|
||||
{"layer", "layer"},
|
||||
};
|
||||
return propertyToRule;
|
||||
};
|
||||
|
@ -911,6 +918,23 @@ QList<OptionsModel::Data> RulesModel::colorSchemesModelData() const
|
|||
return modelData;
|
||||
}
|
||||
|
||||
QList<OptionsModel::Data> RulesModel::layerModelData() const
|
||||
{
|
||||
static const auto modelData = QList<OptionsModel::Data>{
|
||||
{DesktopLayer, i18n("Desktop")},
|
||||
{BelowLayer, i18n("Below")},
|
||||
{NormalLayer, i18n("Normal")},
|
||||
{AboveLayer, i18n("Above")},
|
||||
{NotificationLayer, i18n("Notification")},
|
||||
{ActiveLayer, i18n("Fullscreen")},
|
||||
{PopupLayer, i18n("Popup")},
|
||||
{CriticalNotificationLayer, i18n("Critical Notification")},
|
||||
{OnScreenDisplayLayer, i18n("OSD")},
|
||||
{UnmanagedLayer, i18n("Overlay")},
|
||||
};
|
||||
return modelData;
|
||||
}
|
||||
|
||||
void RulesModel::detectWindowProperties(int miliseconds)
|
||||
{
|
||||
QTimer::singleShot(miliseconds, this, &RulesModel::selectX11Window);
|
||||
|
|
|
@ -102,6 +102,7 @@ private:
|
|||
QList<OptionsModel::Data> placementModelData() const;
|
||||
QList<OptionsModel::Data> focusModelData() const;
|
||||
QList<OptionsModel::Data> colorSchemesModelData() const;
|
||||
QList<OptionsModel::Data> layerModelData() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void selectX11Window();
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace KWin
|
|||
{
|
||||
|
||||
Rules::Rules()
|
||||
: wmclassmatch(UnimportantMatch)
|
||||
: layerrule(UnusedForceRule)
|
||||
, wmclassmatch(UnimportantMatch)
|
||||
, wmclasscomplete(UnimportantMatch)
|
||||
, windowrolematch(UnimportantMatch)
|
||||
, titlematch(UnimportantMatch)
|
||||
|
@ -160,6 +161,7 @@ void Rules::readFromSettings(const RuleSettings *settings)
|
|||
READ_SET_RULE(shortcut);
|
||||
READ_FORCE_RULE(disableglobalshortcuts, );
|
||||
READ_SET_RULE(desktopfile);
|
||||
READ_FORCE_RULE(layer, );
|
||||
}
|
||||
|
||||
#undef READ_MATCH_STRING
|
||||
|
@ -238,6 +240,7 @@ void Rules::write(RuleSettings *settings) const
|
|||
WRITE_SET_RULE(shortcut, Shortcut, );
|
||||
WRITE_FORCE_RULE(disableglobalshortcuts, Disableglobalshortcuts, );
|
||||
WRITE_SET_RULE(desktopfile, Desktopfile, );
|
||||
WRITE_FORCE_RULE(layer, Layer, );
|
||||
}
|
||||
|
||||
#undef WRITE_MATCH_STRING
|
||||
|
@ -282,7 +285,8 @@ bool Rules::isEmpty() const
|
|||
&& strictgeometryrule == UnusedForceRule
|
||||
&& shortcutrule == UnusedSetRule
|
||||
&& disableglobalshortcutsrule == UnusedForceRule
|
||||
&& desktopfilerule == UnusedSetRule);
|
||||
&& desktopfilerule == UnusedSetRule
|
||||
&& layerrule == UnusedForceRule);
|
||||
}
|
||||
|
||||
Rules::ForceRule Rules::convertForceRule(int v)
|
||||
|
@ -575,6 +579,7 @@ APPLY_RULE(ignoregeometry, IgnoreGeometry, bool)
|
|||
APPLY_RULE(screen, Screen, int)
|
||||
APPLY_RULE(activity, Activity, QStringList)
|
||||
APPLY_FORCE_RULE(type, Type, NET::WindowType)
|
||||
APPLY_FORCE_RULE(layer, Layer, enum Layer)
|
||||
|
||||
bool Rules::applyDesktops(QList<VirtualDesktop *> &vds, bool init) const
|
||||
{
|
||||
|
@ -698,6 +703,7 @@ bool Rules::discardUsed(bool withdrawn)
|
|||
DISCARD_USED_SET_RULE(shortcut);
|
||||
DISCARD_USED_FORCE_RULE(disableglobalshortcuts);
|
||||
DISCARD_USED_SET_RULE(desktopfile);
|
||||
DISCARD_USED_FORCE_RULE(layer);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
@ -845,6 +851,7 @@ CHECK_FORCE_RULE(StrictGeometry, bool)
|
|||
CHECK_RULE(Shortcut, QString)
|
||||
CHECK_FORCE_RULE(DisableGlobalShortcuts, bool)
|
||||
CHECK_RULE(DesktopFile, QString)
|
||||
CHECK_FORCE_RULE(Layer, Layer)
|
||||
|
||||
#undef CHECK_RULE
|
||||
#undef CHECK_FORCE_RULE
|
||||
|
|
|
@ -77,6 +77,7 @@ public:
|
|||
QString checkShortcut(QString s, bool init = false) const;
|
||||
bool checkDisableGlobalShortcuts(bool disable) const;
|
||||
QString checkDesktopFile(QString desktopFile, bool init = false) const;
|
||||
Layer checkLayer(Layer layer) const;
|
||||
|
||||
private:
|
||||
MaximizeMode checkMaximizeVert(MaximizeMode mode, bool init) const;
|
||||
|
@ -111,6 +112,7 @@ public:
|
|||
Activity = 1 << 16,
|
||||
Screen = 1 << 17,
|
||||
DesktopFile = 1 << 18,
|
||||
Layer = 1 << 19,
|
||||
All = 0xffffffff
|
||||
};
|
||||
Q_DECLARE_FLAGS(Types, Type)
|
||||
|
@ -184,6 +186,7 @@ public:
|
|||
bool applyShortcut(QString &shortcut, bool init) const;
|
||||
bool applyDisableGlobalShortcuts(bool &disable) const;
|
||||
bool applyDesktopFile(QString &desktopFile, bool init) const;
|
||||
bool applyLayer(enum Layer &layer) const;
|
||||
|
||||
private:
|
||||
#endif
|
||||
|
@ -204,6 +207,8 @@ private:
|
|||
static bool checkSetStop(SetRule rule);
|
||||
static bool checkForceStop(ForceRule rule);
|
||||
#endif
|
||||
enum Layer layer;
|
||||
ForceRule layerrule;
|
||||
QString description;
|
||||
QString wmclass;
|
||||
StringMatch wmclassmatch;
|
||||
|
|
|
@ -431,5 +431,26 @@
|
|||
<max code="true">static_cast<Rules::SetRule>(Rules::ForceTemporarily)</max>
|
||||
<default code="true">Rules::UnusedSetRule</default>
|
||||
</entry>
|
||||
|
||||
<entry name="layer" type="Enum">
|
||||
<label>Layer</label>
|
||||
<choices name="KWin::Layer">
|
||||
<choice name="DesktopLayer" value="desktop" />
|
||||
<choice name="BelowLayer" value="below" />
|
||||
<choice name="NormalLayer" value="normal" />
|
||||
<choice name="AboveLayer" value="above" />
|
||||
<choice name="NotificationLayer" value="notification" />
|
||||
<choice name="ActiveLayer" value="fullscreen" />
|
||||
<choice name="PopupLayer" value="popup" />
|
||||
<choice name="CriticalNotificationLayer" value="critical-notification" />
|
||||
<choice name="OnScreenDisplayLayer" value="osd" />
|
||||
<choice name="UnmanagedLayer" value="overlay" />
|
||||
</choices>
|
||||
<default code="true">NormalLayer</default>
|
||||
</entry>
|
||||
<entry name="layerrule" type="Int">
|
||||
<label>Layer rule type</label>
|
||||
<default code="true">Rules::UnusedForceRule</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
|
|
@ -552,7 +552,7 @@ void Window::markAsDeleted()
|
|||
Layer Window::layer() const
|
||||
{
|
||||
if (m_layer == UnknownLayer) {
|
||||
const_cast<Window *>(this)->m_layer = belongsToLayer();
|
||||
const_cast<Window *>(this)->m_layer = rules()->checkLayer(belongsToLayer());
|
||||
}
|
||||
return m_layer;
|
||||
}
|
||||
|
@ -562,7 +562,7 @@ void Window::updateLayer()
|
|||
if (isDeleted()) {
|
||||
return;
|
||||
}
|
||||
if (layer() == belongsToLayer()) {
|
||||
if (layer() == rules()->checkLayer(belongsToLayer())) {
|
||||
return;
|
||||
}
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
|
@ -4139,6 +4139,7 @@ void Window::applyWindowRules()
|
|||
setFullScreen(isRequestedFullScreen());
|
||||
setNoBorder(noBorder());
|
||||
updateColorScheme();
|
||||
updateLayer();
|
||||
// FSP
|
||||
// AcceptFocus :
|
||||
if (workspace()->mostRecentlyActivatedWindow() == this
|
||||
|
|
Loading…
Reference in a new issue