Skip to content

feat(lockscreen): add power actions to shutdown view - #1417

Open
gugullll wants to merge 1 commit into
linuxdeepin:masterfrom
gugullll:fix/re_shutdownview
Open

gugullll wants to merge 1 commit into
linuxdeepin:masterfrom
gugullll:fix/re_shutdownview

Conversation

@gugullll

@gugullll gugullll commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Merge PowerList into ShutdownView with shutdown, reboot, suspend, hibernate and lock/switch/logout buttons. Adjust focus logic to skip hidden or disabled buttons when opening the power panel.

将关机面板重构成ShutdownView,支持关机/重启/挂起/休眠
及锁屏,切换用户/注销操作,移除原PowerList组件。打开
电源面板时聚焦逻辑会跳过不可见或不可用的按钮。

Log: 重构锁屏关机面板并增加电源操作按钮
PMS: TASK-390751
Influence: 锁屏关机界面提供关机、重启、挂起、休眠等完整
电源操作;电源面板打开时聚焦第一个可见且可用的按钮。交互
和键盘焦点导航相应调整。

Summary by Sourcery

Consolidate lock-screen power controls into ShutdownView and provide complete power-action access with robust focus handling.

New Features:

  • Add shutdown, reboot, suspend, hibernate, lock, switch-user, and logout actions to the lock-screen power panel.

Bug Fixes:

  • Choose the first visible and enabled action when opening the power panel, including when available actions vary by lock state or system permissions.

Enhancements:

  • Merge the former PowerList into ShutdownView and update power-panel focus navigation and dismissal behavior.

Chores:

  • Remove the obsolete PowerList component and update lock-screen translation context and entries.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: gugullll

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai

sourcery-ai Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The lockscreen power panel is refactored around ShutdownView, combining power and session actions while wiring each operation to GreeterProxy/UserModel state. Opening the panel now focuses the first visible, enabled action, with updated cross-action keyboard navigation, dismissal behavior, build configuration, and translations.

Sequence diagram for opening the lockscreen power panel

sequenceDiagram
    participant User
    participant ControlAction
    participant ShutdownView
    participant GreeterProxy
    participant UserModel

    User->>ControlAction: onClicked
    ControlAction->>ShutdownView: focusFirstButton()
    ShutdownView->>GreeterProxy: isLocked
    ShutdownView->>GreeterProxy: canPowerOff
    ShutdownView->>GreeterProxy: canReboot
    ShutdownView->>GreeterProxy: canSuspend
    ShutdownView->>GreeterProxy: canHibernate
    ShutdownView->>UserModel: count
    ShutdownView-->>User: Focus first visible and enabled action
Loading

Flow diagram for consolidated lockscreen power actions

flowchart LR
    ControlAction --> ShutdownView
    ShutdownView --> PowerOff["GreeterProxy.powerOff()"]
    ShutdownView --> Reboot["GreeterProxy.reboot()"]
    ShutdownView --> Suspend["GreeterProxy.suspend()"]
    ShutdownView --> Hibernate["GreeterProxy.hibernate()"]
    ShutdownView --> Lock["GreeterProxy.lock()"]
    ShutdownView --> SwitchUser["UserModel.count and switchUser()"]
    ShutdownView --> Logout["GreeterProxy.logout()"]
Loading

File-Level Changes

Change Details Files
Consolidate all lockscreen power and session actions into a single shutdown panel.
  • Move shutdown, reboot, suspend, and hibernate controls into ShutdownView.
  • Retain lock, user-switching, and logout controls in the same action row.
  • Remove the obsolete PowerList component and its build-module entry.
  • Update translation context and source locations for the consolidated view.
src/plugins/lockscreen/CMakeLists.txt
src/plugins/lockscreen/qml/PowerList.qml
src/plugins/lockscreen/qml/ShutdownView.qml
src/plugins/lockscreen/translations/lockscreen.en_US.ts
Make panel opening and keyboard navigation availability-aware.
  • Focus the first visible and enabled action when the panel opens or becomes visible.
  • Define tab and reverse-tab navigation across the combined action sequence.
  • Use the consolidated ShutdownView for outside-click dismissal and switch-user signaling.
src/plugins/lockscreen/qml/ControlAction.qml
src/plugins/lockscreen/qml/LoginView.qml
src/plugins/lockscreen/qml/ShutdownView.qml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/plugins/lockscreen/qml/ControlAction.qml" line_range="82-90" />
<code_context>

-        Item {
-            id: powerList
+        ShutdownView {
+            id: powerShutdownView
             parent: rootItem
             visible: powerItem.expand
             width: rootItem.width
             height: rootItem.height
             x: 0
             y: 0
-
-            // Click outside the PowerList to close
-            MouseArea {
-                anchors.fill: parent
-                onClicked: {
-                    powerItem.expand = false
-                    innerPowerList.loopInside = false
-                }
-            }
-
-            PowerList {
-                id: innerPowerList
-                width: rootItem.width
-                height: 140
-                x: 0
-                y: rootItem.height / 5 * 2
-            }
+            onOutsideClicked: powerItem.expand = false
         }
         onClicked: {
</code_context>
<issue_to_address>
**issue (bug_risk):** The `ShutdownView` embedded in `ControlAction` emits `switchUser()` when its switch-user button is clicked, but this instance has no `onSwitchUser` handler connected to the existing `otherUserRequested` or login switch-user flow. Clicking Switch User in this power panel therefore performs no action.

**Triggers:** When the power panel is opened while the greeter is unlocked.

**Suggested fix:** Connect `onSwitchUser` to the appropriate `otherUserRequested()`/user-switch handler, or keep the switch-user action only in the top-level `LoginView` shutdown view.
</issue_to_address>

### Comment 2
<location path="src/plugins/lockscreen/qml/ShutdownView.qml" line_range="83" />
<code_context>
+            text: qsTr("Hibernate")
+            icon.name: "login_hibernate"
+            onClicked: GreeterProxy.hibernate()
+            KeyNavigation.tab: lockBtn
+            KeyNavigation.backtab: suspendBtn
+        }
</code_context>
<issue_to_address>
**issue (bug_risk):** The fixed `KeyNavigation` links target buttons that can be invisible or disabled: in the locked state `hibernateBtn` navigates to invisible `lockBtn`, and in the unlocked state `lockBtn` navigates through potentially disabled `switchBtn`. Keyboard focus consequently stops or leaves the intended actionable-button sequence instead of skipping unavailable buttons.

**Triggers:** When a power capability is unavailable, or when the greeter is locked and the lock/switch/logout buttons are hidden.

**Suggested fix:** Build navigation dynamically from the same visible-and-enabled button list used by `focusFirstButton()`, or explicitly link each button to the next available target in both directions.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/plugins/lockscreen/qml/ControlAction.qml
Comment thread src/plugins/lockscreen/qml/ShutdownView.qml
@gugullll gugullll closed this Sep 17, 2026
@gugullll gugullll reopened this Sep 17, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/plugins/lockscreen/qml/ShutdownView.qml" line_range="53-54" />
<code_context>
-                    text: qsTr("Shut Down")
-                    icon.name: "login_shutdown"
-                    onClicked: GreeterProxy.powerOff()
-                    KeyNavigation.tab: rebootBtn
-                    KeyNavigation.backtab: hibernateBtn
-                    Keys.onBacktabPressed: function(event) {
</code_context>
<issue_to_address>
**issue (bug_risk):** The tab cycle points directly to buttons that can be hidden or disabled instead of dynamically skipping them. For example, `hibernateBtn` tabs to hidden `lockBtn` while locked, and `logoutBtn` backtabs to disabled or hidden power buttons, so keyboard focus stops or lands on an unavailable action.

**Triggers:** When a capability disables a power button, or when `GreeterProxy.isLocked` hides the session buttons.

**Suggested fix:** Use navigation logic that selects the next visible and enabled button, or update the navigation targets whenever button visibility or enabled state changes.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/plugins/lockscreen/qml/ShutdownView.qml
Merge PowerList into ShutdownView with shutdown, reboot,
suspend, hibernate and lock/switch/logout buttons. Adjust
focus logic to skip hidden or disabled buttons when opening
the power panel.

将关机面板重构成ShutdownView,支持关机/重启/挂起/休眠
及锁屏,切换用户/注销操作,移除原PowerList组件。打开
电源面板时聚焦逻辑会跳过不可见或不可用的按钮。

Log: 重构锁屏关机面板并增加电源操作按钮
PMS: TASK-390751
Influence: 锁屏关机界面提供关机、重启、挂起、休眠等完整
电源操作;电源面板打开时聚焦第一个可见且可用的按钮。交互
和键盘焦点导航相应调整。
@gugullll gugullll closed this Sep 18, 2026
@gugullll gugullll reopened this Sep 18, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/plugins/lockscreen/qml/ShutdownView.qml" line_range="53-114" />
<code_context>
+            KeyNavigation.tab: rebootBtn
</code_context>
<issue_to_address>
**issue (bug_risk):** Keyboard navigation points directly to buttons that are hidden when disabled or when the lock state changes, so Tab or Backtab stops instead of moving to the next available action. For example, when switching users is unavailable, `lockBtn` navigates to the invisible `switchBtn` rather than `logoutBtn`, and `logoutBtn` navigates to the potentially invisible `powerOffBtn`.

**Triggers:** When one or more power capabilities are unavailable or `UserModel.count` is less than two.

**Suggested fix:** Update the tab and backtab targets dynamically, or implement navigation that searches for the next visible and enabled button before assigning focus.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +53 to +114
KeyNavigation.tab: rebootBtn
KeyNavigation.backtab: logoutBtn
}

ShutdownButton {
id: rebootBtn
enabled: GreeterProxy.canReboot
text: qsTr("Reboot")
icon.name: "login_reboot"
onClicked: GreeterProxy.reboot()
KeyNavigation.tab: suspendBtn
KeyNavigation.backtab: powerOffBtn
}

ShutdownButton {
id: suspendBtn
enabled: GreeterProxy.canSuspend
text: qsTr("Suspend")
icon.name: "login_suspend"
onClicked: GreeterProxy.suspend()
KeyNavigation.tab: hibernateBtn
KeyNavigation.backtab: rebootBtn
}

ShutdownButton {
id: hibernateBtn
enabled: GreeterProxy.canHibernate
text: qsTr("Hibernate")
icon.name: "login_hibernate"
onClicked: GreeterProxy.hibernate()
KeyNavigation.tab: lockBtn
KeyNavigation.backtab: suspendBtn
}

ShutdownButton {
id: lockBtn
visible: !GreeterProxy.isLocked
text: qsTr("lock")
icon.name: "login_lock"
onClicked: GreeterProxy.lock()
KeyNavigation.tab: switchBtn
KeyNavigation.backtab: hibernateBtn
}

ShutdownButton {
id: switchBtn
visible: !GreeterProxy.isLocked
text: qsTr("switch user")
icon.name: "login_switchuser"
enabled: UserModel.count > 1
onClicked: root.switchUser()
KeyNavigation.tab: logoutBtn
KeyNavigation.backtab: lockBtn
}

ShutdownButton {
id: logoutBtn
visible: !GreeterProxy.isLocked
text: qsTr("Logout")
icon.name: "login_logout"
onClicked: GreeterProxy.logout()
KeyNavigation.tab: powerOffBtn

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Keyboard navigation points directly to buttons that are hidden when disabled or when the lock state changes, so Tab or Backtab stops instead of moving to the next available action. For example, when switching users is unavailable, lockBtn navigates to the invisible switchBtn rather than logoutBtn, and logoutBtn navigates to the potentially invisible powerOffBtn.

Triggers: When one or more power capabilities are unavailable or UserModel.count is less than two.

Suggested fix: Update the tab and backtab targets dynamically, or implement navigation that searches for the next visible and enabled button before assigning focus.

@gugullll gugullll closed this Sep 21, 2026
@gugullll gugullll reopened this Sep 21, 2026
@gugullll gugullll closed this Sep 29, 2026
@gugullll gugullll reopened this Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants