diff --git a/abstract_client.cpp b/abstract_client.cpp --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -366,6 +366,8 @@ return OnScreenDisplayLayer; if (isNotification()) return NotificationLayer; + if (isCriticalNotification()) + return CriticalNotificationLayer; if (workspace()->showingDesktop() && belongsToDesktop()) { return AboveLayer; } @@ -477,7 +479,7 @@ bool AbstractClient::isSpecialWindow() const { // TODO - return isDesktop() || isDock() || isSplash() || isToolbar() || isNotification() || isOnScreenDisplay(); + return isDesktop() || isDock() || isSplash() || isToolbar() || isNotification() || isOnScreenDisplay() || isCriticalNotification(); } void AbstractClient::demandAttention(bool set) diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp --- a/autotests/integration/internal_window.cpp +++ b/autotests/integration/internal_window.cpp @@ -741,6 +741,7 @@ QTest::newRow("Notification") << NET::Notification; QTest::newRow("ComboBox") << NET::ComboBox; QTest::newRow("OnScreenDisplay") << NET::OnScreenDisplay; + QTest::newRow("CriticalNotification") << NET::CriticalNotification; } void InternalWindowTest::testWindowType() @@ -776,6 +777,7 @@ QTest::newRow("Notification") << NET::Notification; QTest::newRow("ComboBox") << NET::ComboBox; QTest::newRow("OnScreenDisplay") << NET::OnScreenDisplay; + QTest::newRow("CriticalNotification") << NET::CriticalNotification; } void InternalWindowTest::testChangeWindowType() diff --git a/autotests/integration/plasma_surface_test.cpp b/autotests/integration/plasma_surface_test.cpp --- a/autotests/integration/plasma_surface_test.cpp +++ b/autotests/integration/plasma_surface_test.cpp @@ -107,6 +107,7 @@ QTest::newRow("Normal") << PlasmaShellSurface::Role::Normal << false; QTest::newRow("Notification") << PlasmaShellSurface::Role::Notification << true; QTest::newRow("ToolTip") << PlasmaShellSurface::Role::ToolTip << true; + QTest::newRow("CriticalNotification") << PlasmaShellSurface::Role::CriticalNotification << true; } void PlasmaSurfaceTest::testRoleOnAllDesktops() @@ -164,6 +165,7 @@ QTest::newRow("Normal") << PlasmaShellSurface::Role::Normal << true << true; QTest::newRow("Notification") << PlasmaShellSurface::Role::Notification << false << false; QTest::newRow("ToolTip") << PlasmaShellSurface::Role::ToolTip << false << false; + QTest::newRow("CriticalNotification") << PlasmaShellSurface::Role::CriticalNotification << false << false; } void PlasmaSurfaceTest::testAcceptsFocus() diff --git a/autotests/test_window_paint_data.cpp b/autotests/test_window_paint_data.cpp --- a/autotests/test_window_paint_data.cpp +++ b/autotests/test_window_paint_data.cpp @@ -176,6 +176,9 @@ bool isNotification() const override { return false; } + bool isCriticalNotification() const override { + return false; + } bool isOnScreenDisplay() const override { return false; } diff --git a/client.cpp b/client.cpp --- a/client.cpp +++ b/client.cpp @@ -511,6 +511,7 @@ case NET::Splash : case NET::Notification : case NET::OnScreenDisplay : + case NET::CriticalNotification : noborder = true; app_noborder = true; break; diff --git a/debug_console.cpp b/debug_console.cpp --- a/debug_console.cpp +++ b/debug_console.cpp @@ -1054,6 +1054,8 @@ return QStringLiteral("NET::DNDIcon"); case NET::OnScreenDisplay: return QStringLiteral("NET::OnScreenDisplay"); + case NET::CriticalNotification: + return QStringLiteral("NET::CriticalNotification"); case NET::Unknown: default: return QStringLiteral("NET::Unknown"); diff --git a/effects.h b/effects.h --- a/effects.h +++ b/effects.h @@ -432,6 +432,7 @@ bool isPopupMenu() const override; bool isTooltip() const override; bool isNotification() const override; + bool isCriticalNotification() const override; bool isOnScreenDisplay() const override; bool isComboBox() const override; bool isDNDIcon() const override; diff --git a/effects.cpp b/effects.cpp --- a/effects.cpp +++ b/effects.cpp @@ -1822,6 +1822,7 @@ TOPLEVEL_HELPER(bool, isPopupMenu, isPopupMenu) TOPLEVEL_HELPER(bool, isTooltip, isTooltip) TOPLEVEL_HELPER(bool, isNotification, isNotification) +TOPLEVEL_HELPER(bool, isCriticalNotification, isCriticalNotification) TOPLEVEL_HELPER(bool, isOnScreenDisplay, isOnScreenDisplay) TOPLEVEL_HELPER(bool, isComboBox, isComboBox) TOPLEVEL_HELPER(bool, isDNDIcon, isDNDIcon) diff --git a/effects/fadingpopups/package/contents/code/main.js b/effects/fadingpopups/package/contents/code/main.js --- a/effects/fadingpopups/package/contents/code/main.js +++ b/effects/fadingpopups/package/contents/code/main.js @@ -68,7 +68,8 @@ // special windows(e.g. notifications) because the monolithic version // was doing that. if (window.dock || window.splash || window.toolbar - || window.notification || window.onScreenDisplay) { + || window.notification || window.onScreenDisplay + || window.criticalNotification) { return true; } diff --git a/effects/morphingpopups/package/contents/code/morphingpopups.js b/effects/morphingpopups/package/contents/code/morphingpopups.js --- a/effects/morphingpopups/package/contents/code/morphingpopups.js +++ b/effects/morphingpopups/package/contents/code/morphingpopups.js @@ -28,7 +28,7 @@ geometryChange: function (window, oldGeometry) { //only tooltips and notifications - if (!window.tooltip && !window.notification) { + if (!window.tooltip && !window.notification && !window.criticalNotification) { return; } diff --git a/layers.cpp b/layers.cpp --- a/layers.cpp +++ b/layers.cpp @@ -40,12 +40,15 @@ Every window has one layer assigned in which it is. There are 7 layers, from bottom : DesktopLayer, BelowLayer, NormalLayer, DockLayer, AboveLayer, NotificationLayer, - ActiveLayer and OnScreenDisplayLayer (see also NETWM sect.7.10.). The layer a window is in depends - on the window type, and on other things like whether the window is active. We extend the layers - provided in NETWM by the NotificationLayer and OnScreenDisplayLayer. + ActiveLayer, CriticalNotificationLayer, and OnScreenDisplayLayer (see also NETWM sect.7.10.). + The layer a window is in depends on the window type, and on other things like whether the window + is active. We extend the layers provided in NETWM by the NotificationLayer, OnScreenDisplayLayer, + and CriticalNotificationLayer. The NoficationLayer contains notification windows which are kept above all windows except the active - fullscreen window. The OnScreenDisplayLayer is used for eg. volume and brightness change feedback and - is kept above all windows since it provides immediate response to a user action. + fullscreen window. The CriticalNotificationLayer contains notification windows which are important + enough to keep them even above fullscreen windows. The OnScreenDisplayLayer is used for eg. volume + and brightness change feedback and is kept above all windows since it provides immediate response + to a user action. NET::Splash clients belong to the Normal layer. NET::TopMenu clients belong to Dock layer. Clients that are both NET::Dock and NET::KeepBelow diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1881,6 +1881,11 @@ * See _NET_WM_WINDOW_TYPE_NOTIFICATION at https://standards.freedesktop.org/wm-spec/wm-spec-latest.html . **/ Q_PROPERTY(bool notification READ isNotification) + /** + * Returns whether the window is a window with a critical notification. + * using the non-standard _KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION + **/ + Q_PROPERTY(bool criticalNotification READ isCriticalNotification) /** * Returns whether the window is an on screen display window * using the non-standard _KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY @@ -2258,6 +2263,11 @@ * See _NET_WM_WINDOW_TYPE_NOTIFICATION at https://standards.freedesktop.org/wm-spec/wm-spec-latest.html . **/ virtual bool isNotification() const = 0; + /** + * Returns whether the window is a window with a critical notification. + * using the non-standard _KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION + **/ + virtual bool isCriticalNotification() const = 0; /** * Returns whether the window is an on screen display window * using the non-standard _KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY diff --git a/placement.cpp b/placement.cpp --- a/placement.cpp +++ b/placement.cpp @@ -70,7 +70,7 @@ placeDialog(c, area, options->placement()); else if (c->isSplash()) placeOnMainWindow(c, area); // on mainwindow, if any, otherwise centered - else if (c->isOnScreenDisplay() || c->isNotification()) + else if (c->isOnScreenDisplay() || c->isNotification() || c->isCriticalNotification()) placeOnScreenDisplay(c, area); else if (c->isTransient() && c->hasTransientPlacementHint()) placeTransient(c); diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -1045,7 +1045,8 @@ if (m_plasmaShellSurface) { if (m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::OnScreenDisplay || m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::ToolTip || - m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::Notification) { + m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::Notification || + m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::CriticalNotification) { return false; } } @@ -1230,14 +1231,17 @@ case PlasmaShellSurfaceInterface::Role::ToolTip: type = NET::Tooltip; break; + case PlasmaShellSurfaceInterface::Role::CriticalNotification: + type = NET::CriticalNotification; + break; case PlasmaShellSurfaceInterface::Role::Normal: default: type = NET::Normal; break; } if (type != m_windowType) { m_windowType = type; - if (m_windowType == NET::Desktop || type == NET::Dock || type == NET::OnScreenDisplay || type == NET::Notification || type == NET::Tooltip) { + if (m_windowType == NET::Desktop || type == NET::Dock || type == NET::OnScreenDisplay || type == NET::Notification || type == NET::Tooltip || type == NET::CriticalNotification) { setOnAllDesktops(true); } workspace()->updateClientArea(); diff --git a/toplevel.h b/toplevel.h --- a/toplevel.h +++ b/toplevel.h @@ -160,6 +160,10 @@ * See _NET_WM_WINDOW_TYPE_NOTIFICATION at https://standards.freedesktop.org/wm-spec/wm-spec-latest.html . **/ Q_PROPERTY(bool notification READ isNotification) + /** + * Returns whether the window is a window with a critical notification. + **/ + Q_PROPERTY(bool criticalNotification READ isCriticalNotification) /** * Returns whether the window is an On Screen Display. **/ @@ -284,6 +288,7 @@ bool isPopupMenu() const; // a context popup, not dropdown, not torn-off bool isTooltip() const; bool isNotification() const; + bool isCriticalNotification() const; bool isOnScreenDisplay() const; bool isComboBox() const; bool isDNDIcon() const; @@ -747,6 +752,11 @@ return windowType() == NET::Notification; } +inline bool Toplevel::isCriticalNotification() const +{ + return windowType() == NET::CriticalNotification; +} + inline bool Toplevel::isOnScreenDisplay() const { return windowType() == NET::OnScreenDisplay; diff --git a/utils.h b/utils.h --- a/utils.h +++ b/utils.h @@ -46,12 +46,14 @@ // window types that are supported as normal windows (i.e. KWin actually manages them) const NET::WindowTypes SUPPORTED_MANAGED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask - | NET::UtilityMask | NET::SplashMask | NET::NotificationMask | NET::OnScreenDisplayMask; + | NET::UtilityMask | NET::SplashMask | NET::NotificationMask | NET::OnScreenDisplayMask + | NET::CriticalNotificationMask; // window types that are supported as unmanaged (mainly for compositing) const NET::WindowTypes SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask | NET::DropdownMenuMask | NET::PopupMenuMask - | NET::TooltipMask | NET::NotificationMask | NET::ComboBoxMask | NET::DNDIconMask | NET::OnScreenDisplayMask; + | NET::TooltipMask | NET::NotificationMask | NET::ComboBoxMask | NET::DNDIconMask | NET::OnScreenDisplayMask + | NET::CriticalNotificationMask; const QPoint invalidPoint(INT_MIN, INT_MIN); @@ -82,6 +84,7 @@ AboveLayer, NotificationLayer, // layer for windows of type notification ActiveLayer, // active fullscreen, or active dialog + CriticalNotificationLayer, // layer for notifications that should be shown even on top of fullscreen OnScreenDisplayLayer, // layer for On Screen Display windows such as volume feedback UnmanagedLayer, // layer for override redirect windows. NumLayers // number of layers, must be last