Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions panels/notification/center/GroupNotify.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand Down Expand Up @@ -111,7 +111,6 @@ NotifyItem {
icon.name: "clean-group"
text: qsTr("Clear All")
Keys.onTabPressed: function(event) {
groupClearBtn.focus = false // Clear focus before signal to prevent focus state residue
root.gotoNextItem()
event.accepted = true
}
Expand Down
18 changes: 7 additions & 11 deletions panels/notification/center/NormalNotify.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -13,7 +13,6 @@ NotifyItem {
id: root
implicitWidth: impl.implicitWidth
implicitHeight: impl.implicitHeight
property bool shouldShowClose: false // True when item gets focus from keyboard navigation

signal gotoNextItem()
signal gotoPrevItem()
Expand All @@ -32,19 +31,16 @@ NotifyItem {
focus: true

Keys.onTabPressed: function(event) {
// Mark that this item got focus from Tab navigation
root.shouldShowClose = true
if (notifyContent.focusFirstButton()) {
event.accepted = true
} else {
if (!notifyContent.focusFirstButton()) {
root.gotoNextItem()
event.accepted = true
}
event.accepted = true
}

Keys.onBacktabPressed: function(event) {
root.shouldShowClose = true
root.gotoPrevItem()
if (!notifyContent.focusLastButton()) {
root.gotoPrevItem()
}
event.accepted = true
}

Expand All @@ -59,7 +55,7 @@ NotifyItem {
actions: root.actions
defaultAction: root.defaultAction
// Show close button when: mouse hovers, or item has focus from keyboard navigation
parentHovered: impl.hovered || (root.activeFocus && root.shouldShowClose)
parentHovered: impl.hovered || root.activeFocus
strongInteractive: root.strongInteractive
contentIcon: root.contentIcon
contentRowCount: root.contentRowCount
Expand Down
1 change: 0 additions & 1 deletion panels/notification/center/NotifyHeader.qml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ FocusScope {
text: qsTr("Clear All")
Layout.alignment: Qt.AlignRight
Keys.onTabPressed: function(event) {
clearAllBtn.focus = false // Clear focus before signal to prevent focus state residue
root.gotoFirstNotify()
event.accepted = true
}
Expand Down
4 changes: 3 additions & 1 deletion panels/notification/center/NotifyView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ Control {
function tryFocus(retries) {
let item = view.itemAtIndex(idx)
if (item && item.enabled) {
item.forceActiveFocus()
if (!item.focusFirstButton()) {
item.forceActiveFocus()
}
} else if (retries > 0) {
Qt.callLater(function() { tryFocus(retries - 1) })
}
Expand Down
11 changes: 2 additions & 9 deletions panels/notification/center/NotifyViewDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ DelegateChooser {
Qt.callLater(function() {
let nextItem = view.itemAtIndex(currentIndex + 1)
if (nextItem && nextItem.enabled) {
// Focus on the item itself first, not directly to buttons
nextItem.forceActiveFocus()
}
})
Expand All @@ -43,7 +42,6 @@ DelegateChooser {
Qt.callLater(function() {
let prevItem = view.itemAtIndex(currentIndex - 1)
if (prevItem && prevItem.enabled) {
// Focus on the item itself first, not directly to buttons
prevItem.forceActiveFocus()
}
})
Expand Down Expand Up @@ -177,8 +175,8 @@ DelegateChooser {
activeFocusOnTab: false
focusBorderVisible: activeFocus
Keys.onTabPressed: function(event) {
// Try to focus first action button
if (overlapNotify.focusFirstButton()) {
// Try to focus first action button (skip clear button to avoid loop)
if (notifyContent.focusFirstActionOnly()) {
event.accepted = true
return
}
Expand All @@ -196,11 +194,6 @@ DelegateChooser {
}
}

Component.onCompleted: {
// Pass clear button reference to OverlapNotify
overlapNotify.clearButton = clearBtn
}

TapHandler {
acceptedButtons: Qt.RightButton
onPressedChanged: function () {
Expand Down
19 changes: 8 additions & 11 deletions panels/notification/center/OverlapNotify.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -17,15 +17,14 @@ NotifyItem {
property int count: 1
readonly property int overlapItemRadius: 12
property bool enableDismissed: true
property bool shouldShowClose: false // True when item gets focus from keyboard navigation
property var removedCallback
property alias notifyContent: notifyContent

signal expand()
signal gotoNextItem()
signal gotoPrevItem()

property var clearButton: null // Reference to the externally defined clear button
property var clearButton: notifyContent.clearButtonItem

function focusFirstButton() {
// Focus clear button first, then action buttons
Expand Down Expand Up @@ -77,18 +76,16 @@ NotifyItem {
focus: true

Keys.onTabPressed: function(event) {
root.shouldShowClose = true
if (notifyContent.focusFirstButton()) {
event.accepted = true
} else {
if (!notifyContent.focusFirstButton()) {
root.gotoNextItem()
event.accepted = true
}
event.accepted = true
}

Keys.onBacktabPressed: function(event) {
root.shouldShowClose = true
root.gotoPrevItem()
if (!notifyContent.focusLastButton()) {
root.gotoPrevItem()
}
event.accepted = true
}

Expand All @@ -106,7 +103,7 @@ NotifyItem {
actions: root.actions
defaultAction: root.defaultAction
// Show close button when: mouse hovers, or item has focus from keyboard navigation
parentHovered: impl.hovered || (root.activeFocus && root.shouldShowClose)
parentHovered: impl.hovered || root.activeFocus
strongInteractive: root.strongInteractive
contentIcon: root.contentIcon
contentRowCount: root.contentRowCount
Expand Down
6 changes: 3 additions & 3 deletions panels/notification/plugin/NotifyItemContent.qml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ NotifyItem {
// Maximum retry attempts for focus operations when loader content is pending
readonly property int maxFocusRetries: 5
property bool parentHovered: false // External hover state from parent component
property bool closeVisible: activeFocus || impl.hovered || parentHovered || (clearLoader.item && clearLoader.item.activeFocus)
property bool closeVisible: activeFocus || impl.hovered || parentHovered
property int miniContentHeight: NotifyStyle.contentItem.miniHeight
property bool enableDismissed: true
property alias clearButton: clearLoader.sourceComponent
readonly property alias clearButtonItem: clearLoader.item

signal gotoNextItem() // Signal to navigate to next notify item
signal gotoPrevItem() // Signal to navigate to previous notify item
Comment on lines +19 to 26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Re-evaluate visibility/activation conditions now that clear button focus is no longer considered explicitly.

Previously, closeVisible and clearLoader.active stayed true while the clear button itself had focus by checking clearLoader.item && clearLoader.item.activeFocus. Now closeVisible relies only on root.activeFocus and hover. In many QML hierarchies only the focused child has activeFocus, so when the close button gains focus, root.activeFocus may become false, hiding/unloading the button while it is still focused. Please verify whether root keeps activeFocus when the close button is focused; if not, consider reintroducing a focus check tied directly to the clear/close button (e.g., its activeFocus) in these conditions.

Expand Down Expand Up @@ -111,8 +112,7 @@ NotifyItem {
id: clearLoader
anchors.right: parent.right
// Show when mouse hovers or notification item has focus
// Keep active when button itself has focus to prevent unloading during Tab navigation
active: !(root.strongInteractive && root.actions.length > 0) && (root.closeVisible || closePlaceHolder.hovered || (clearLoader.item && clearLoader.item.activeFocus))
active: !(root.strongInteractive && root.actions.length > 0) && (root.closeVisible || closePlaceHolder.hovered)
sourceComponent: SettingActionButton {
id: closeBtn
objectName: "closeNotify-" + root.appName
Expand Down
Loading