Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package btop for openSUSE:Factory checked in 
at 2025-09-22 19:29:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/btop (Old)
 and      /work/SRC/openSUSE:Factory/.btop.new.27445 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "btop"

Mon Sep 22 19:29:16 2025 rev:39 rq:1306565 version:1.4.4+git20250910.bdddfc4

Changes:
--------
--- /work/SRC/openSUSE:Factory/btop/btop.changes        2025-07-31 
17:50:15.866285513 +0200
+++ /work/SRC/openSUSE:Factory/.btop.new.27445/btop.changes     2025-09-22 
19:29:18.705928456 +0200
@@ -1,0 +2,38 @@
+Mon Sep 15 13:55:27 UTC 2025 - Scott Bradnick <[email protected]>
+
+- Commenting out code for RSMI_STATIC
+  * Removing rocm_smi_lib-rocm-6.4.3.tar.gz
+  * Adding 'Recommends: rocm-smi'
+- Update to version 1.4.4+git20250910.bdddfc4:
+  * Enable vim movement in help menu (#1242)
+  * Remove reduntant symbols in tree view (#948)
+  * Use /sys/dev/block/MAJOR:MINOR instead of /sys/block/NAME for disk I/O
+  * Don't terminate on GPU access failure
+  * fix: setcap cap_dac_read_search was overriding cap_perfmon
+  * Fix musl builds missing artifacts
+  * chore(deps): update actions/checkout action to v5
+  * chore(deps): update actions/checkout action to v5
+  * Update README.md
+  * feat: display CPU power draw & fix GPU+load avg overwriting core info
+  * refactor: remove reduntant casts and avoid conversions
+  * Revert unnecessary locale changes and remove debug line.
+
+-------------------------------------------------------------------
+Thu Aug 07 15:08:30 UTC 2025 - Scott Bradnick <[email protected]>
+
+- Updating ROCm to v6.4.3
+- Update to version 1.4.4+git20250805.a05192f:
+  * fix: disable locale when writing config file
+  * Update CODE_OF_CONDUCT.md
+  * match formatting for units
+  * fix layout issue when enc/dec meters are unavailable
+  * disable encode/decode monitoring on AMD and Intel GPUs
+  * impl encode/decode monitoring for Nvidia
+  * Add utilisation meters for GPU hardware video encoder and decoder
+  * linux-batt: Battery Time-to-full
+  * Convert ascii escape codes in mountpoint names before reading statvfs.
+  * Fix presets erroring with gpu* usage.
+  * Clarify where btop loads themes from
+  * Update "cpu responsive" to "cpu direct" in README.md (#1199)
+
+-------------------------------------------------------------------

Old:
----
  btop-1.4.4+git20250718.86ec5fd.tar.gz
  rocm_smi_lib-rocm-6.4.2.tar.gz

New:
----
  btop-1.4.4+git20250910.bdddfc4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ btop.spec ++++++
--- /var/tmp/diff_new_pack.K2fSxJ/_old  2025-09-22 19:29:19.713970908 +0200
+++ /var/tmp/diff_new_pack.K2fSxJ/_new  2025-09-22 19:29:19.713970908 +0200
@@ -15,21 +15,27 @@
 # Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
-%define ROCm_version 6.4.2
+### 20250915: TO_BE_REMOVED
+#%%define ROCm_version 6.4.3
+#####
 Name:           btop
-Version:        1.4.4+git20250718.86ec5fd
+Version:        1.4.4+git20250910.bdddfc4
 Release:        0
 Summary:        Usage and stats for processor, memory, disks, network and 
processes
 License:        Apache-2.0
 Group:          System/Monitoring
 URL:            https://github.com/aristocratos/btop
 Source0:        %{name}-%{version}.tar.gz
-Source1:        
https://github.com/ROCm/rocm_smi_lib/archive/refs/tags/rocm-%{ROCm_version}.tar.gz#/rocm_smi_lib-rocm-%{ROCm_version}.tar.gz
+### 20250915: TO_BE_REMOVED
+#Source1:        
https://github.com/ROCm/rocm_smi_lib/archive/refs/tags/rocm-%%{ROCm_version}.tar.gz#/rocm_smi_lib-rocm-%%{ROCm_version}.tar.gz
+#####
 Source99:       btop-rpmlintrc
 Patch0:         Makefile.diff
 BuildRequires:  coreutils
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(libdrm)
+#BuildRequires:  rocm-smi
+#BuildRequires:  rocm-smi-devel
 BuildRequires:  sed
 %if 0%{?suse_version} < 1550
 BuildRequires:  gcc13-c++
@@ -48,6 +54,7 @@
 %define cxxopt %{nil}
 %define lddopt %{nil}
 %endif
+Recommends:     rocm-smi
 
 %description
 Resource monitor that shows usage and stats for processor, memory, disks,
@@ -55,15 +62,20 @@
 
 %prep
 %autosetup -p0
-cd %{_builddir}/%{name}-%{version}
-mkdir -vp %{_builddir}/%{name}-%{version}/lib/rocm_smi_lib
-tar zxf %{SOURCE1} -C %{_builddir}/%{name}-%{version}/lib/rocm_smi_lib 
--strip-components=1
+### 20250915: TO_BE_REMOVED
+#cd %%{_builddir}/%%{name}-%%{version}
+#mkdir -vp %%{_builddir}/%%{name}-%%{version}/lib/rocm_smi_lib
+#tar zxf %%{SOURCE1} -C %%{_builddir}/%%{name}-%%{version}/lib/rocm_smi_lib 
--strip-components=1
+#####
 
 %build
 ###
 ### RSMI_STATIC will break with gcc-14, as of <= v6.1.2 (20240606)
 ###
-%make_build %{cxxflags} %{cxxopt} %{lddopt} RSMI_STATIC=true
+%make_build %{cxxflags} %{cxxopt} %{lddopt}
+### 20250915: TO_BE_REMOVED
+#RSMI_STATIC=true
+#####
 
 %install
 %make_install %{cxxopt} %{lddopt} PREFIX=%{_prefix}

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.K2fSxJ/_old  2025-09-22 19:29:19.757972761 +0200
+++ /var/tmp/diff_new_pack.K2fSxJ/_new  2025-09-22 19:29:19.761972929 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/aristocratos/btop</param>
-              <param 
name="changesrevision">86ec5fd06282a96ae46542e653490b7144e801f9</param></service></servicedata>
+              <param 
name="changesrevision">bdddfc46a2bbfe4ba70c7fba4fbb30978d61dab9</param></service></servicedata>
 (No newline at EOF)
 

++++++ btop-1.4.4+git20250718.86ec5fd.tar.gz -> 
btop-1.4.4+git20250910.bdddfc4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-freebsd.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-freebsd.yml
--- old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-freebsd.yml      
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-freebsd.yml      
2025-09-10 17:49:55.000000000 +0200
@@ -33,7 +33,7 @@
         arch: ['aarch64', 'x86_64']
         version: ['14.3', '15.0']
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Compile
         uses: vmactions/freebsd-vm@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-linux.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-linux.yml
--- old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-linux.yml        
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-linux.yml        
2025-09-10 17:49:55.000000000 +0200
@@ -44,7 +44,7 @@
           - compiler: gcc
             version: 14
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Install clang ${{ matrix.version }}
         if: ${{ matrix.compiler == 'clang' }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-macos.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-macos.yml
--- old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-macos.yml        
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-macos.yml        
2025-09-10 17:49:55.000000000 +0200
@@ -28,7 +28,7 @@
       group: ${{ github.workflow }}-${{ github.event.pull_request.number || 
github.ref }}
       cancel-in-progress: true
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Install build tools
         run: |
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-netbsd.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-netbsd.yml
--- old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/cmake-netbsd.yml       
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/cmake-netbsd.yml       
2025-09-10 17:49:55.000000000 +0200
@@ -33,7 +33,7 @@
         arch: ['aarch64', 'amd64']
         version: ['10.1']
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Compile
         uses: vmactions/netbsd-vm@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-freebsd.yml
 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-freebsd.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-freebsd.yml
   2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-freebsd.yml
   2025-09-10 17:49:55.000000000 +0200
@@ -37,7 +37,7 @@
       matrix:
         compiler: ["clang++", "g++"]
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Compile
         uses: vmactions/freebsd-vm@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-gpu.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-gpu.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-gpu.yml   
    2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-gpu.yml   
    2025-09-10 17:49:55.000000000 +0200
@@ -37,7 +37,7 @@
       group: ${{ github.workflow }}-${{ github.event.pull_request.number || 
github.ref }}
       cancel-in-progress: true
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Install build tools
         run: apk add --no-cache --update gcc g++ make linux-headers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-linux.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-linux.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-linux.yml 
    2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-linux.yml 
    2025-09-10 17:49:55.000000000 +0200
@@ -90,14 +90,17 @@
     container: muslcc/x86_64:${{ matrix.toolchain }}
 
     steps:
+      - name: Update alpine repositories
+        run: sed -i 's/3\.14/3\.22/' /etc/apk/repositories
+
       - name: Install build tools
-        run: apk add --no-cache coreutils git make tar zstd
+        run: apk add --no-cache --upgrade coreutils git make tar zstd
 
       - name: Fix - Unsafe repository stop
         run: git config --global --add safe.directory /__w/btop/btop
 
       - name: Checkout source
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           submodules: recursive
 
@@ -126,4 +129,5 @@
         uses: actions/upload-artifact@v4
         with:
           name: btop-${{ matrix.toolchain }}
-          path: '.artifacts/**'
+          path: '${{ github.workspace }}/.artifacts/*'
+          include-hidden-files: true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-macos.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-macos.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-macos.yml 
    2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-macos.yml 
    2025-09-10 17:49:55.000000000 +0200
@@ -43,7 +43,7 @@
         with:
           xcode-version: latest-stable
 
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Install build tools
         run: |
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-netbsd.yml
 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-netbsd.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-netbsd.yml
    2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-netbsd.yml
    2025-09-10 17:49:55.000000000 +0200
@@ -34,7 +34,7 @@
     runs-on: ubuntu-24.04
     timeout-minutes: 20
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Compile
         uses: vmactions/netbsd-vm@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-openbsd.yml
 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-openbsd.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/continuous-build-openbsd.yml
   2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/continuous-build-openbsd.yml
   2025-09-10 17:49:55.000000000 +0200
@@ -34,7 +34,7 @@
     runs-on: ubuntu-24.04
     timeout-minutes: 20
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - name: Compile
         uses: vmactions/openbsd-vm@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/test-snap-can-build.yml 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/test-snap-can-build.yml
--- 
old/btop-1.4.4+git20250718.86ec5fd/.github/workflows/test-snap-can-build.yml    
    2025-07-18 00:20:18.000000000 +0200
+++ 
new/btop-1.4.4+git20250910.bdddfc4/.github/workflows/test-snap-can-build.yml    
    2025-09-10 17:49:55.000000000 +0200
@@ -34,7 +34,7 @@
         node-version: [20.x]
 
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
 
       - uses: snapcore/action-build@v1
         id: build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/CODE_OF_CONDUCT.md 
new/btop-1.4.4+git20250910.bdddfc4/CODE_OF_CONDUCT.md
--- old/btop-1.4.4+git20250718.86ec5fd/CODE_OF_CONDUCT.md       2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/CODE_OF_CONDUCT.md       2025-09-10 
17:49:55.000000000 +0200
@@ -1,76 +1,93 @@
-# Contributor Covenant Code of Conduct
+
+# Contributor Covenant 3.0
 
 ## Our Pledge
 
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, 
body
-size, disability, ethnicity, sex characteristics, gender identity and 
expression,
-level of experience, education, socio-economic status, nationality, personal
-appearance, race, religion, or sexual identity and orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery and unwelcome sexual attention or
- advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
+We pledge to make our community welcoming, safe, and equitable for all.
+
+We are committed to fostering an environment that respects and promotes the 
dignity, rights, and contributions of all individuals, regardless of 
characteristics including race, ethnicity, caste, color, age, physical 
characteristics, neurodiversity, disability, sex or gender, gender identity or 
expression, sexual orientation, language, philosophy or religion, national or 
social origin, socio-economic position, level of education, or other status. 
The same privileges of participation are extended to everyone who participates 
in good faith and in accordance with this Covenant.
+
+
+## Encouraged Behaviors
+
+While acknowledging differences in social norms, we all strive to meet our 
community's expectations for positive behavior. We also understand that our 
words and actions may be interpreted differently than we intend based on 
culture, background, or native language.
+
+With these considerations in mind, we agree to behave mindfully toward each 
other and act in ways that center our shared values, including:
+
+1. Respecting the **purpose of our community**, our activities, and our ways 
of gathering.
+2. Engaging **kindly and honestly** with others.
+3. Respecting **different viewpoints** and experiences.
+4. **Taking responsibility** for our actions and contributions.
+5. Gracefully giving and accepting **constructive feedback**.
+6. Committing to **repairing harm** when it occurs.
+7. Behaving in other ways that promote and sustain the **well-being of our 
community**.
+
+
+## Restricted Behaviors
+
+We agree to restrict the following behaviors in our community. Instances, 
threats, and promotion of these behaviors are violations of this Code of 
Conduct.
+
+1. **Harassment.** Violating explicitly expressed boundaries or engaging in 
unnecessary personal attention after any clear request to stop.
+2. **Character attacks.** Making insulting, demeaning, or pejorative comments 
directed at a community member or group of people.
+3. **Stereotyping or discrimination.** Characterizing anyone’s personality or 
behavior on the basis of immutable identities or traits.
+4. **Sexualization.** Behaving in a way that would generally be considered 
inappropriately intimate in the context or purpose of the community.
+5. **Violating confidentiality**. Sharing or acting on someone's personal or 
private information without their permission.
+6. **Endangerment.** Causing, encouraging, or threatening violence or other 
harm toward any person or group.
+7. Behaving in other ways that **threaten the well-being** of our community.
+
+### Other Restrictions
+
+1. **Misleading identity.** Impersonating someone else for any reason, or 
pretending to be someone else to evade enforcement actions.
+2. **Failing to credit sources.** Not properly crediting the sources of 
content you contribute.
+3. **Promotional materials**. Sharing marketing or other commercial content in 
a way that is outside the norms of the community.
+4. **Irresponsible communication.** Failing to responsibly present content 
which includes, links or describes any other restricted behaviors.
+
+
+## Reporting an Issue
+
+Tensions can occur between community members even when they are trying their 
best to collaborate. Not every conflict represents a code of conduct violation, 
and this Code of Conduct reinforces encouraged behaviors and norms that can 
help avoid conflicts and minimize harm.
+
+When an incident does occur, it is important to report it promptly. To report 
a possible violation, **[NOTE: describe your means of reporting here.]**
+
+Community Moderators take reports of violations seriously and will make every 
effort to respond in a timely manner. They will investigate all reports of code 
of conduct violations, reviewing messages, logs, and recordings, or 
interviewing witnesses and other participants. Community Moderators will keep 
investigation and enforcement actions as transparent as possible while 
prioritizing safety and confidentiality. In order to honor these values, 
enforcement actions are carried out in private with the involved parties, but 
communicating to the whole community may be part of a mutually agreed upon 
resolution.
+
+
+## Addressing and Repairing Harm
+
+**[NOTE: The remedies and repairs outlined below are suggestions based on best 
practices in code of conduct enforcement. If your community has its own 
established enforcement process, be sure to edit this section to describe your 
own policies.]**
+
+If an investigation by the Community Moderators finds that this Code of 
Conduct has been violated, the following enforcement ladder may be used to 
determine how best to repair harm, based on the incident's impact on the 
individuals involved and the community as a whole. Depending on the severity of 
a violation, lower rungs on the ladder may be skipped.
+
+1) Warning
+   1) Event: A violation involving a single incident or series of incidents.
+   2) Consequence: A private, written warning from the Community Moderators.
+   3) Repair: Examples of repair include a private written apology, 
acknowledgement of responsibility, and seeking clarification on expectations.
+2) Temporarily Limited Activities
+   1) Event: A repeated incidence of a violation that previously resulted in a 
warning, or the first incidence of a more serious violation.
+   2) Consequence: A private, written warning with a time-limited cooldown 
period designed to underscore the seriousness of the situation and give the 
community members involved time to process the incident. The cooldown period 
may be limited to particular communication channels or interactions with 
particular community members.
+   3) Repair: Examples of repair may include making an apology, using the 
cooldown period to reflect on actions and impact, and being thoughtful about 
re-entering community spaces after the period is over.
+3) Temporary Suspension
+   1) Event: A pattern of repeated violation which the Community Moderators 
have tried to address with warnings, or a single serious violation.
+   2) Consequence: A private written warning with conditions for return from 
suspension. In general, temporary suspensions give the person being suspended 
time to reflect upon their behavior and possible corrective actions.
+   3) Repair: Examples of repair include respecting the spirit of the 
suspension, meeting the specified conditions for return, and being thoughtful 
about how to reintegrate with the community when the suspension is lifted.
+4) Permanent Ban
+   1) Event: A pattern of repeated code of conduct violations that other steps 
on the ladder have failed to resolve, or a violation so serious that the 
Community Moderators determine there is no way to keep the community safe with 
this person as a member.
+   2) Consequence: Access to all community spaces, tools, and communication 
channels is removed. In general, permanent bans should be rarely used, should 
have strong reasoning behind them, and should only be resorted to if working 
through other remedies has failed to change the behavior.
+   3) Repair: There is no possible repair in cases of this severity.
+
+This enforcement ladder is intended as a guideline. It does not limit the 
ability of Community Managers to use their discretion and judgment, in keeping 
with the best interests of our community.
+
 
 ## Scope
 
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an 
appointed
-representative at an online or offline event. Representation of a project may 
be
-further defined and clarified by project maintainers.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at [email protected]. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an 
incident.
-Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
+This Code of Conduct applies within all community spaces, and also applies 
when an individual is officially representing the community in public or other 
spaces. Examples of representing our community include using an official email 
address, posting via an official social media account, or acting as an 
appointed representative at an online or offline event.
+
 
 ## Attribution
 
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], 
version 1.4,
-available at 
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+This Code of Conduct is adapted from the Contributor Covenant, version 3.0, 
permanently available at 
[https://www.contributor-covenant.org/version/3/0/](https://www.contributor-covenant.org/version/3/0/).
+
+Contributor Covenant is stewarded by the Organization for Ethical Source and 
licensed under CC BY-SA 4.0. To view a copy of this license, visit 
[https://creativecommons.org/licenses/by-sa/4.0/](https://creativecommons.org/licenses/by-sa/4.0/)
 
-[homepage]: https://www.contributor-covenant.org
+For answers to common questions about Contributor Covenant, see the FAQ at 
[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq).
 Translations are provided at 
[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations).
 Additional enforcement and community guideline resources can be found at 
[https://www.contributor-covenant.org/resources](https://www.contributor-covenant.org/resources).
 The enforcement ladder was inspired by the work of [Mozilla’s code of conduct 
team](https://github.com/mozilla/inclusion).
 
-For answers to common questions about this code of conduct, see
-https://www.contributor-covenant.org/faq
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/Makefile 
new/btop-1.4.4+git20250910.bdddfc4/Makefile
--- old/btop-1.4.4+git20250718.86ec5fd/Makefile 2025-07-18 00:20:18.000000000 
+0200
+++ new/btop-1.4.4+git20250910.bdddfc4/Makefile 2025-09-10 17:49:55.000000000 
+0200
@@ -333,7 +333,7 @@
 setcap:
        @printf "\033[1;97mFile: $(DESTDIR)$(PREFIX)/bin/btop\n"
        @printf "\033[1;92mSetting capabilities...\033[0m\n"
-       @setcap cap_perfmon=+ep $(DESTDIR)$(PREFIX)/bin/btop
+       @setcap "cap_perfmon=+ep cap_dac_read_search=+ep" 
$(DESTDIR)$(PREFIX)/bin/btop
 
 # With 'rm -v' user will see what files (if any) got removed
 uninstall:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/README.md 
new/btop-1.4.4+git20250910.bdddfc4/README.md
--- old/btop-1.4.4+git20250718.86ec5fd/README.md        2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/README.md        2025-09-10 
17:49:55.000000000 +0200
@@ -203,12 +203,26 @@
 
 ## Themes
 
-Btop++ uses the same theme files as bpytop and bashtop (some color values 
missing in bashtop themes) .
+Btop++ uses the same theme files as bpytop and bashtop (some color values 
missing in bashtop themes).
 
 See [themes](https://github.com/aristocratos/btop/tree/main/themes) folder for 
available themes.
 
+Btop searches the following directories for system themes:
+
+* `../share/btop/themes` (this path is relative to the btop executable)
+* `/usr/local/share/btop/themes`
+* `/usr/share/btop/themes`
+
+The first directory that exists and isn't empty is used as the system themes 
directory.
+
+The user themes directory depends on which environment variables are set:
+
+* If `$XDG_CONFIG_HOME` is set, the user themes directory is 
`$XDG_CONFIG_HOME/btop/themes`
+* Otherwise, if `$HOME` is set, the user themes directory is 
`$HOME/.config/btop/themes`
+* Otherwise, the user themes directory is `~/.config/btop/themes`
+
 The `make install` command places the default themes in `[$PREFIX or 
/usr/local]/share/btop/themes`.
-User created themes should be placed in `$XDG_CONFIG_HOME/btop/themes` or 
`$HOME/.config/btop/themes`.
+User created themes should be placed in the user themes directory.
 
 Let me know if you want to contribute with new themes.
 
@@ -317,11 +331,11 @@
    sudo make install
    ```
 
-3. **(Optional/Required for Intel GPU) Set extended capabilities or suid bit 
to btop**
+3. **(Optional/Required for Intel GPU and CPU wattage) Set extended 
capabilities or suid bit to btop**
 
    Enables signal sending to any process without starting with `sudo` and can 
prevent /proc read permissions problems on some systems.
 
-   Is required for Intel GPU support.
+   Is required for Intel GPU support and CPU wattage monitoring.
 
    * **Run:**
 
@@ -471,11 +485,11 @@
 
    Notice! Only use "sudo" when installing to a NON user owned directory.
 
-5. **(Optional/Required for Intel GPU support) Set extended capabilities or 
suid bit to btop**
+5. **(Optional/Required for Intel GPU support and CPU wattage) Set extended 
capabilities or suid bit to btop**
 
    No need for `sudo` to enable signal sending to any process and to prevent 
/proc read permissions problems on some systems.
 
-   Also required for Intel GPU monitoring.
+   Also required for Intel GPU monitoring and CPU wattage monitoring.
 
    Run after make install and use same PREFIX if any was used at install.
 
@@ -1340,8 +1354,8 @@
 #* Update time in milliseconds, recommended 2000 ms or above for better sample 
times for graphs.
 update_ms = 1500
 
-#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" 
"cpu lazy" "cpu responsive",
-#* "cpu lazy" sorts top process over time (easier to follow), "cpu responsive" 
updates top process directly.
+#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" 
"cpu lazy" "cpu direct",
+#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" 
updates top process directly.
 proc_sorting = "cpu lazy"
 
 #* Reverse sorting order, True or False.
@@ -1388,6 +1402,9 @@
 #* Shows the system uptime in the CPU box.
 show_uptime = True
 
+#* Shows the CPU package current power consumption in watts. Requires running 
`make setcap` or `make setuid` or running with sudo.
+show_cpu_watts = True
+
 #* Show cpu temperature.
 check_temp = True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/src/btop.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/btop.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/btop.cpp     2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/btop.cpp     2025-09-10 
17:49:55.000000000 +0200
@@ -898,7 +898,6 @@
        //? Try to find and set a UTF-8 locale
        if (std::setlocale(LC_ALL, "") != nullptr and not 
s_contains((string)std::setlocale(LC_ALL, ""), ";")
        and str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", 
"")).ends_with("UTF8")) {
-               std::locale::global(std::locale(std::setlocale(LC_ALL, "")));
                Logger::debug("Using locale " + std::locale().name());
        }
        else {
@@ -921,7 +920,6 @@
                                                        if 
(str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) {
                                                                found = 
l.substr(l.find('=') + 1);
                                                                if 
(std::setlocale(LC_ALL, found.c_str()) != nullptr) {
-                                                                       
std::locale::global(std::locale(found));
                                                                        break;
                                                                }
                                                        }
@@ -943,11 +941,9 @@
                                Logger::warning("No UTF-8 locale detected! Some 
symbols might not display correctly.");
                        }
                        else if (std::setlocale(LC_ALL, string(cur_locale + 
".UTF-8").c_str()) != nullptr) {
-                               std::locale::global(std::locale(cur_locale + 
".UTF-8"));
                                Logger::debug("Setting LC_ALL=" + cur_locale + 
".UTF-8");
                        }
                        else if(std::setlocale(LC_ALL, "en_US.UTF-8") != 
nullptr) {
-                               std::locale::global(std::locale("en_US.UTF-8"));
                                Logger::debug("Setting LC_ALL=en_US.UTF-8");
                        }
                        else {
@@ -977,8 +973,6 @@
                Logger::info("Running on " + Term::current_tty);
        }
 
-       Logger::debug(to_string(1.0).substr(1,1));
-
        configure_tty_mode(cli.force_tty);
 
        //? Check for valid terminal dimensions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/src/btop_config.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/btop_config.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/btop_config.cpp      2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/btop_config.cpp      2025-09-10 
17:49:55.000000000 +0200
@@ -20,6 +20,7 @@
 #include <atomic>
 #include <filesystem>
 #include <fstream>
+#include <locale>
 #include <optional>
 #include <ranges>
 #include <string_view>
@@ -131,6 +132,8 @@
 
                {"show_uptime",                 "#* Shows the system uptime in 
the CPU box."},
 
+               {"show_cpu_watts",              "#* Shows the CPU package 
current power consumption in watts. Requires running `make setcap` or `make 
setuid` or running with sudo."},
+
                {"check_temp",                  "#* Show cpu temperature."},
 
                {"cpu_sensor",                  "#* Which sensor to use for cpu 
temperature, use options menu to select from list of available sensors."},
@@ -280,6 +283,7 @@
                {"cpu_single_graph", false},
                {"cpu_bottom", false},
                {"show_uptime", true},
+               {"show_cpu_watts", true},
                {"check_temp", true},
                {"show_coretemp", true},
                {"show_cpu_freq", true},
@@ -467,7 +471,11 @@
                        } else if (vals.at(0) == "proc") {
                                set("proc_left", (vals.at(1) != "0"));
                        }
-                       set("graph_symbol_" + vals.at(0), vals.at(2));
+                       if (vals.at(0).starts_with("gpu")) {
+                               set("graph_symbol_gpu", vals.at(2));
+                       } else {
+                               set("graph_symbol_" + vals.at(0), vals.at(2));
+                       }
                }
 
                if (set_boxes(boxes)) {
@@ -760,6 +768,7 @@
                Logger::debug("Writing new config file");
                if (geteuid() != Global::real_uid and seteuid(Global::real_uid) 
!= 0) return;
                std::ofstream cwrite(conf_file, std::ios::trunc);
+               cwrite.imbue(std::locale::classic());
                if (cwrite.good()) {
                        cwrite << "#? Config file for btop v. " << 
Global::Version << "\n";
                        for (const auto& [name, description] : descriptions) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/src/btop_draw.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/btop_draw.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/btop_draw.cpp        2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/btop_draw.cpp        2025-09-10 
17:49:55.000000000 +0200
@@ -519,7 +519,8 @@
        int x = 1, y = 1, width = 20, height;
        int b_columns, b_column_size;
        int b_x, b_y, b_width, b_height;
-       long unsigned int lavg_str_len = 0;
+       float max_observed_pwr = 1.0f;
+
        int graph_up_height, graph_low_height;
        int graph_up_width, graph_low_width;
        int gpu_meter_width;
@@ -538,6 +539,7 @@
                if (Runner::stopping) return "";
                if (force_redraw) redraw = true;
                bool show_temps = (Config::getB("check_temp") and got_sensors);
+               bool show_watts = (Config::getB("show_cpu_watts") and 
supports_watts);
                auto single_graph = Config::getB("cpu_single_graph");
                bool hide_cores = show_temps and (cpu_temp_only or not 
Config::getB("show_coretemp"));
                const int extra_width = (hide_cores ? max(6, 6 * b_column_size) 
: 0);
@@ -584,7 +586,6 @@
                        graph_up_height = (single_graph ? height - 2 : 
ceil((double)(height - 2) / 2) - (mid_line and height % 2 != 0));
                        graph_low_height = height - 2 - graph_up_height - 
mid_line;
                        const int button_y = cpu_bottom ? y + height - 1 : y;
-                       lavg_str_len = 0;
                        out += box;
 
                        //? Buttons on title
@@ -681,7 +682,12 @@
                        }
                        #endif
 
-                       cpu_meter = Draw::Meter{b_width - (show_temps ? 23 - 
(b_column_size <= 1 and b_columns == 1 ? 6 : 0) : 11), "cpu"};
+                       int cpu_meter_width = b_width - (show_temps ? 23 - 
(b_column_size <= 1 and b_columns == 1 ? 6 : 0) : 11);
+                       if (show_watts) {
+                               cpu_meter_width -= 6;
+                       }
+
+                       cpu_meter = Draw::Meter{cpu_meter_width, "cpu"};
 
                        if (mid_line) {
                                out += Mv::to(y + graph_up_height + 1, x) + 
Fx::ub + Theme::c("cpu_box") + Symbols::div_left + Theme::c("div_line")
@@ -752,58 +758,64 @@
                }
 
                try {
-               //? Cpu/Gpu graphs
-               out += Fx::ub + Mv::to(y + 1, x + 1);
-               auto draw_graphs = [&](vector<Draw::Graph>& graphs, const int 
graph_height, const int graph_width, const string& graph_field) {
-               #ifdef GPU_SUPPORT
-                       if (graph_field.starts_with("gpu"))
-                               if (graph_field.ends_with("totals")) {
-                                       int gpu_drawn = 0;
-                                       for (size_t i = 0; i < gpus.size(); 
i++) {
-                                               if (gpu_auto and 
v_contains(Gpu::shown_panels, i))
-                                                       continue;
-                                               out += 
graphs[i](safeVal(gpus[i].gpu_percent, graph_field), (data_same or redraw));
-                                               if (Gpu::count - (gpu_auto ? 
Gpu::shown : 0) > 1) {
-                                                       auto i_str = 
to_string(i);
-                                                       out += 
Mv::l(graph_width-1) + Mv::u(graph_height/2) + (graph_width > 5 ? "GPU" : "") + 
i_str
-                                                               + 
Mv::d(graph_height/2) + Mv::r(graph_width - 1 - (graph_width > 5)*3 - 
i_str.size());
-                                               }
+                       //? Cpu/Gpu graphs
+                       out += Fx::ub + Mv::to(y + 1, x + 1);
+                       auto draw_graphs = [&](vector<Draw::Graph>& graphs, 
const int graph_height, const int graph_width, const string& graph_field) {
+                       #ifdef GPU_SUPPORT
+                               if (graph_field.starts_with("gpu"))
+                                       if (graph_field.ends_with("totals")) {
+                                               int gpu_drawn = 0;
+                                               for (size_t i = 0; i < 
gpus.size(); i++) {
+                                                       if (gpu_auto and 
v_contains(Gpu::shown_panels, i)) {
+                                                               continue;
+                                                       }
+                                                       try {
+                                                               const auto& 
gpu_percent = gpus[i].gpu_percent;
+                                                               out += 
graphs[i](safeVal(gpu_percent, graph_field), (data_same or redraw));
+                                                       } catch 
(std::out_of_range& /* unused */) {
+                                                               continue;
+                                                       }
+                                                       if (Gpu::count - 
(gpu_auto ? Gpu::shown : 0) > 1) {
+                                                               auto i_str = 
to_string(i);
+                                                               out += 
Mv::l(graph_width-1) + Mv::u(graph_height/2) + (graph_width > 5 ? "GPU" : "") + 
i_str
+                                                                       + 
Mv::d(graph_height/2) + Mv::r(graph_width - 1 - (graph_width > 5)*3 - 
i_str.size());
+                                                       }
 
-                                               if (++gpu_drawn < Gpu::count - 
(gpu_auto ? Gpu::shown : 0))
-                                                       out += 
Theme::c("div_line") + (Symbols::v_line + Mv::l(1) + Mv::u(1))*graph_height + 
Mv::r(1) + Mv::d(1);
+                                                       if (++gpu_drawn < 
Gpu::count - (gpu_auto ? Gpu::shown : 0))
+                                                               out += 
Theme::c("div_line") + (Symbols::v_line + Mv::l(1) + Mv::u(1))*graph_height + 
Mv::r(1) + Mv::d(1);
+                                               }
                                        }
-                               }
+                                       else
+                                               out += 
graphs[0](safeVal(Gpu::shared_gpu_percent, graph_field), (data_same or redraw));
                                else
-                                       out += 
graphs[0](safeVal(Gpu::shared_gpu_percent, graph_field), (data_same or redraw));
-                       else
-               #else
-                       (void)graph_height;
-                       (void)graph_width;
-               #endif
-                               out += graphs[0](safeVal(cpu.cpu_percent, 
graph_field), (data_same or redraw));
-               };
+                       #else
+                               (void)graph_height;
+                               (void)graph_width;
+                       #endif
+                                       out += 
graphs[0](safeVal(cpu.cpu_percent, graph_field), (data_same or redraw));
+                       };
 
-               draw_graphs(graphs_upper, graph_up_height, graph_up_width, 
graph_up_field);
-               if (not single_graph) {
-                       out += Mv::to(y + graph_up_height + 1 + mid_line, x + 
1);
-                       draw_graphs(graphs_lower, graph_low_height, 
graph_low_width, graph_lo_field);
-               }
-
-               //? Uptime
-               if (Config::getB("show_uptime")) {
-                       string upstr = sec_to_dhms(system_uptime());
-                       if (upstr.size() > 8) {
-                               upstr.resize(upstr.size() - 3);
-                               upstr = trans(upstr);
-                       }
-                       out += Mv::to(y + (single_graph or not 
Config::getB("cpu_invert_lower") ? 1 : height - 2), x + 2)
-                               + Theme::c("graph_text") + "up" + Mv::r(1) + 
upstr;
-               }
-
-               //? Cpu clock and cpu meter
-               if (Config::getB("show_cpu_freq") and not cpuHz.empty())
-                       out += Mv::to(b_y, b_x + b_width - 10) + Fx::ub + 
Theme::c("div_line") + Symbols::h_line * (7 - cpuHz.size())
-                               + Symbols::title_left + Fx::b + 
Theme::c("title") + cpuHz + Fx::ub + Theme::c("div_line") + 
Symbols::title_right;
+                       draw_graphs(graphs_upper, graph_up_height, 
graph_up_width, graph_up_field);
+                       if (not single_graph) {
+                               out += Mv::to(y + graph_up_height + 1 + 
mid_line, x + 1);
+                               draw_graphs(graphs_lower, graph_low_height, 
graph_low_width, graph_lo_field);
+                       }
+
+                       //? Uptime
+                       if (Config::getB("show_uptime")) {
+                               string upstr = sec_to_dhms(system_uptime());
+                               if (upstr.size() > 8) {
+                                       upstr.resize(upstr.size() - 3);
+                                       upstr = trans(upstr);
+                               }
+                               out += Mv::to(y + (single_graph or not 
Config::getB("cpu_invert_lower") ? 1 : height - 2), x + 2)
+                                       + Theme::c("graph_text") + "up" + 
Mv::r(1) + upstr;
+                       }
+
+                       //? Cpu clock and cpu meter
+                       if (Config::getB("show_cpu_freq") and not cpuHz.empty())
+                               out += Mv::to(b_y, b_x + b_width - 10) + Fx::ub 
+ Theme::c("div_line") + Symbols::h_line * (7 - cpuHz.size())
+                                       + Symbols::title_left + Fx::b + 
Theme::c("title") + cpuHz + Fx::ub + Theme::c("div_line") + 
Symbols::title_right;
 
                out += Mv::to(b_y + 1, b_x + 1) + Theme::c("main_fg") + Fx::b + 
"CPU " + cpu_meter(safeVal(cpu.cpu_percent, "total"s).back())
                        + Theme::g("cpu").at(clamp(safeVal(cpu.cpu_percent, 
"total"s).back(), 0ll, 100ll)) + rjust(to_string(safeVal(cpu.cpu_percent, 
"total"s).back()), 4) + Theme::c("main_fg") + '%';
@@ -815,9 +827,26 @@
                                        + temp_graphs.at(0)(safeVal(cpu.temp, 
0), data_same or redraw);
                        out += rjust(to_string(temp), 4) + Theme::c("main_fg") 
+ unit;
                }
-               out += Theme::c("div_line") + Symbols::v_line;
 
-               } catch (const std::exception& e) { throw 
std::runtime_error("graphs, clock, meter : " + string{e.what()}); }
+               if (show_watts) {
+                       string cwatts = fmt::format(" {:>4.{}f}", 
cpu.usage_watts, cpu.usage_watts < 10.0f ? 2 : cpu.usage_watts < 100.0f ? 1 : 
0);
+                       string cwatts_post = "W";
+
+                       max_observed_pwr = max(max_observed_pwr, 
cpu.usage_watts);
+                       out += Theme::g("cached").at(clamp(cpu.usage_watts / 
max_observed_pwr * 100.0f, 0.0f, 100.0f)) + cwatts + Theme::c("main_fg") + 
cwatts_post; 
+               }
+
+                       out += Theme::c("div_line") + Symbols::v_line;
+               } catch (const std::exception& e) {
+                       throw std::runtime_error("graphs, clock, meter : " + 
string{e.what()});
+               }
+
+               int max_row = b_height - 3; // Subtracting one extra row for 
the load average (and power if enabled)
+               int n_gpus_to_show = 0;
+       #ifdef GPU_SUPPORT
+               n_gpus_to_show = show_gpu ? (gpus.size() - (gpu_always ? 0 : 
Gpu::shown)) : 0;
+       #endif
+               max_row -= n_gpus_to_show;
 
                //? Core text and graphs
                int cx = 0, cy = 1, cc = 0, core_width = (b_column_size == 0 ? 
2 : 3);
@@ -843,7 +872,7 @@
 
                        out += Theme::c("div_line") + Symbols::v_line;
 
-                       if ((++cy > ceil((double)Shared::coreCount / b_columns) 
or cy == b_height - 2) and n != Shared::coreCount - 1) {
+                       if ((++cy > ceil((double)Shared::coreCount / b_columns) 
or cy == max_row) and n != Shared::coreCount - 1) {
                                if (++cc >= b_columns) break;
                                cy = 1; cx = (b_width / b_columns) * cc;
                        }
@@ -851,28 +880,17 @@
 
                //? Load average
                if (cy < b_height - 1 and cc <= b_columns) {
-                       string lavg_pre;
-                       int sep = 1;
-                       if (b_column_size == 2 and show_temps) { lavg_pre = 
"Load AVG: "; sep = 3; }
-                       else if (b_column_size == 2 or (b_column_size == 1 and 
show_temps)) { lavg_pre = "LAV:"; }
-                       else if (b_column_size == 1 or (b_column_size == 0 and 
show_temps)) { lavg_pre = "L "; }
-                       string lavg;
+                       cy = b_height - 2 - n_gpus_to_show;
+
+                       string load_avg_pre = "Load avg:";
+                       string load_avg;
+
                        for (const auto& val : cpu.load_avg) {
-                               lavg += string(sep, ' ') + (lavg_pre.size() < 3 
? fmt::format("{:.0f}", val) : fmt::format("{:.2f}", val));
+                               load_avg += fmt::format(" {:.2f}", val);
                        }
 
-                       string lavg_str = lavg_pre + lavg;
-                       if (lavg_str_len > lavg_str.length()) {
-                               lavg_str += string(lavg_str_len - 
lavg_str.length(), ' ');
-                       } else {
-                               lavg_str_len = lavg_str.length();
-                       }
-               #ifdef GPU_SUPPORT
-                       cy = b_height - 2 - (show_gpu ? (gpus.size() - 
(gpu_always ? 0 : Gpu::shown)) : 0);
-               #else
-                       cy = b_height - 2;
-               #endif
-                       out += Mv::to(b_y + cy, b_x + cx + 1) + 
Theme::c("main_fg") + lavg_str;
+                       int len = load_avg_pre.size() + load_avg.size();
+                       out += Mv::to(b_y + cy, b_x + 1) + string(max(b_width - 
len - 2, 0), ' ') + Theme::c("main_fg") + Fx::b + load_avg_pre + Fx::ub + 
load_avg;
                }
 
        #ifdef GPU_SUPPORT
@@ -947,6 +965,7 @@
        vector<Draw::Graph> mem_used_graph_vec = {}, mem_util_graph_vec = {};
        vector<Draw::Meter> gpu_meter_vec = {};
        vector<Draw::Meter> pwr_meter_vec = {};
+       vector<Draw::Meter> enc_meter_vec = {};
        vector<string> box = {};
 
     string draw(const gpu_info& gpu, unsigned long index, bool force_redraw, 
bool data_same) {
@@ -964,6 +983,7 @@
                auto& mem_util_graph = mem_util_graph_vec[index];
                auto& gpu_meter = gpu_meter_vec[index];
                auto& pwr_meter = pwr_meter_vec[index];
+               auto& enc_meter = enc_meter_vec[index];
 
                if (force_redraw) redraw[index] = true;
         bool show_temps = gpu.supported_functions.temp_info and 
(Config::getB("check_temp"));
@@ -1002,6 +1022,8 @@
                                mem_util_graph = Draw::Graph{b_width/2 - 1, 2, 
"free", gpu.mem_utilization_percent, graph_symbol, 0, 0, 100, 4}; // offset so 
the graph isn't empty at 0-5% utilization
                        if (gpu.supported_functions.mem_used and 
gpu.supported_functions.mem_total)
                                mem_used_graph = Draw::Graph{b_width/2 - 2, 2 + 
2*(gpu.supported_functions.mem_utilization), "used", safeVal(gpu.gpu_percent, 
"gpu-vram-totals"s), graph_symbol};
+                       if (gpu.supported_functions.encoder_utilization)
+                               enc_meter = Draw::Meter{b_width/2 - 10, "cpu"};
                }
 
 
@@ -1041,8 +1063,17 @@
                                out += std::string(" P-state: ") + 
(gpu.pwr_state > 9 ? "" : " ") + 'P' + 
Theme::g("cached").at(clamp(gpu.pwr_state, 0ll, 100ll)) + 
to_string(gpu.pwr_state);
                }
 
+               //? Encode and Decode meters
+               bool drawnEncDec = gpu.supported_functions.encoder_utilization 
and gpu.supported_functions.decoder_utilization;
+               if (drawnEncDec) {
+                       out += Mv::to(b_y + 3, b_x +1) + Theme::c("main_fg") + 
Fx::b + "ENC " + enc_meter(gpu.encoder_utilization)
+                               + 
Theme::g("cpu").at(clamp(gpu.encoder_utilization, 0ll, 100ll)) + 
rjust(to_string(gpu.encoder_utilization), 4) + Theme::c("main_fg") + '%'
+                               + Theme::c("div_line") + Symbols::v_line + 
Theme::c("main_fg") + Fx::b + "DEC " + enc_meter(gpu.decoder_utilization)
+                               + 
Theme::g("cpu").at(clamp(gpu.decoder_utilization, 0ll, 100ll)) + 
rjust(to_string(gpu.decoder_utilization), 4) + Theme::c("main_fg") + '%';
+               }
+
                if (gpu.supported_functions.mem_total or 
gpu.supported_functions.mem_used) {
-                       out += Mv::to(b_y + 3, b_x);
+                       out += Mv::to(b_y + (drawnEncDec ? 4 : 3), b_x);
                        if (gpu.supported_functions.mem_total and 
gpu.supported_functions.mem_used) {
                                string used_memory_string = 
floating_humanizer(gpu.mem_used);
 
@@ -1067,7 +1098,7 @@
                                //? Memory clock speed
                                if (gpu.supported_functions.mem_clock) {
                                        string clock_speed_string = 
to_string(gpu.mem_clock_speed);
-                                       out += Mv::to(b_y + 3, b_x + b_width/2 
- 11) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size())
+                                       out += Mv::to(b_y + (drawnEncDec ? 4 : 
3), b_x + b_width/2 - 11) + Theme::c("div_line") + 
Symbols::h_line*(5-clock_speed_string.size())
                                                + Symbols::title_left + Fx::b + 
Theme::c("title") + clock_speed_string + " MHz" + Fx::ub + Theme::c("div_line") 
+ Symbols::title_right;
                                }
                        } else {
@@ -2100,6 +2131,7 @@
                        mem_used_graph_vec.resize(shown); 
mem_util_graph_vec.resize(shown);
                        gpu_meter_vec.resize(shown);
                        pwr_meter_vec.resize(shown);
+                       enc_meter_vec.resize(shown);
                        redraw.resize(shown);
                        for (auto i = 0; i < shown; ++i) {
                                redraw[i] = true;
@@ -2120,7 +2152,7 @@
                                box[i] = createBox(x_vec[i], y_vec[i], width, 
height, Theme::c("cpu_box"), true, std::string("gpu") + 
(char)(shown_panels[i]+'0'), "", (shown_panels[i]+5)%10); // TODO gpu_box
 
                                b_height_vec[i] = 2 + 
gpu_b_height_offsets[shown_panels[i]];
-                               b_width = clamp(width/2, min_width, 64);
+                               b_width = clamp(width/2, min_width, 65);
 
                                //? Main statistics box
                                b_x_vec[i] = x_vec[i] + width - b_width - 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/src/btop_menu.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/btop_menu.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/btop_menu.cpp        2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/btop_menu.cpp        2025-09-10 
17:49:55.000000000 +0200
@@ -510,6 +510,13 @@
                                "\"/uptime\" in the formatting.",
                                "",
                                "True or False."},
+                       {"show_cpu_watts",
+                               "Shows the CPU power consumption in watts.",
+                               "",
+                               "Requires running `make setcap` or",
+                               "`make setuid` or running with sudo.",
+                               "",
+                               "True or False."},
                },
        #ifdef GPU_SUPPORT
                {
@@ -1557,10 +1564,10 @@
                else if (is_in(key, "escape", "q", "h", "backspace", "space", 
"enter", "mouse_click")) {
                        return Closed;
                }
-               else if (pages > 1 and is_in(key, "down", "page_down", "tab", 
"mouse_scroll_down")) {
+               else if (pages > 1 and is_in(key, "down", "j", "page_down", 
"tab", "mouse_scroll_down")) {
                        if (++page >= pages) page = 0;
                }
-               else if (pages > 1 and is_in(key, "up", "page_up", "shift_tab", 
"mouse_scroll_up")) {
+               else if (pages > 1 and is_in(key, "up", "k", "page_up", 
"shift_tab", "mouse_scroll_up")) {
                        if (--page < 0) page = pages - 1;
                }
                else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/src/btop_shared.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/btop_shared.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/btop_shared.cpp      2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/btop_shared.cpp      2025-09-10 
17:49:55.000000000 +0200
@@ -181,7 +181,6 @@
 
        void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, 
vector<tree_proc>& out_procs,
                int cur_depth, bool collapsed, const string& filter, bool 
found, bool no_update, bool should_filter) {
-               auto cur_pos = out_procs.size();
                bool filtering = false;
 
                //? If filtering, include children of matching processes
@@ -241,17 +240,18 @@
                                cur_proc.threads += p.threads;
                        }
                }
-               if (collapsed or filtering) {
-                       return;
-               }
-
-               //? Add tree terminator symbol if it's the last child in a 
sub-tree
-               if (out_procs.back().children.size() > 0 and 
out_procs.back().children.back().entry.get().prefix.size() >= 8 and not 
out_procs.back().children.back().entry.get().prefix.ends_with("]─"))
-                       
out_procs.back().children.back().entry.get().prefix.replace(out_procs.back().children.back().entry.get().prefix.size()
 - 8, 8, " └─ ");
-
-               //? Add collapse/expand symbols if process have any children
-               out_procs.at(cur_pos).entry.get().prefix = " │ "s * cur_depth + 
(out_procs.at(cur_pos).children.size() > 0 ? (cur_proc.collapsed ? "[+]─" : 
"[-]─") : " ├─ ");
-
        }
 
+       void _collect_prefixes(tree_proc &t, const bool is_last, const string 
&header) {
+               const bool is_filtered = t.entry.get().filtered;
+               if (is_filtered) t.entry.get().depth = 0;
+
+               if (!t.children.empty()) t.entry.get().prefix = header + 
(t.entry.get().collapsed ? "[+]─": "[-]─");
+               else t.entry.get().prefix = header + (is_last ? " └─": " ├─");
+
+               for (auto child = t.children.begin(); child != 
t.children.end(); ++child) {
+                       _collect_prefixes(*child, child == (t.children.end() - 
1),
+                               is_filtered ? "": header + (is_last ? "   ": " 
│ "));
+               }
+       }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/btop-1.4.4+git20250718.86ec5fd/src/btop_shared.hpp 
new/btop-1.4.4+git20250910.bdddfc4/src/btop_shared.hpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/btop_shared.hpp      2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/btop_shared.hpp      2025-09-10 
17:49:55.000000000 +0200
@@ -139,7 +139,9 @@
                                 temp_info = true,
                                 mem_total = true,
                                 mem_used = true,
-                                pcie_txrx = true;
+                                pcie_txrx = true,
+                                encoder_utilization = true,
+                                decoder_utilization = true;
        };
 
        //* Per-device container for GPU info
@@ -166,6 +168,9 @@
                long long pcie_tx = 0; // KB/s
                long long pcie_rx = 0;
 
+               long long encoder_utilization = 0;
+               long long decoder_utilization = 0;
+
                gpu_info_supported supported_functions;
 
                // vector<proc_info> graphics_processes = {}; // TODO
@@ -194,7 +199,7 @@
 namespace Cpu {
        extern string box;
        extern int x, y, width, height, min_width, min_height;
-       extern bool shown, redraw, got_sensors, cpu_temp_only, has_battery;
+       extern bool shown, redraw, got_sensors, cpu_temp_only, has_battery, 
supports_watts;
        extern string cpuName, cpuHz;
        extern vector<string> available_fields;
        extern vector<string> available_sensors;
@@ -218,6 +223,7 @@
                vector<deque<long long>> temp;
                long long temp_max = 0;
                array<double, 3> load_avg;
+               float usage_watts = 0;
        };
 
        //* Collect cpu stats and temperatures
@@ -438,4 +444,7 @@
        void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, 
vector<tree_proc>& out_procs,
                                   int cur_depth, bool collapsed, const string& 
filter,
                                   bool found = false, bool no_update = false, 
bool should_filter = false);
+
+       //* Build prefixes for tree view
+       void _collect_prefixes(tree_proc& t, bool is_last, const string &header 
= "");
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/src/freebsd/btop_collect.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/freebsd/btop_collect.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/freebsd/btop_collect.cpp     
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/freebsd/btop_collect.cpp     
2025-09-10 17:49:55.000000000 +0200
@@ -78,7 +78,7 @@
        vector<string> available_fields = {"Auto", "total"};
        vector<string> available_sensors = {"Auto"};
        cpu_info current_cpu;
-       bool got_sensors = false, cpu_temp_only = false;
+       bool got_sensors = false, cpu_temp_only = false, supports_watts = false;
 
        //* Populate found_sensors map
        bool get_sensors();
@@ -1266,13 +1266,10 @@
                        int index = 0;
                        tree_sort(tree_procs, sorting, reverse, index, 
current_procs.size());
 
-                       //? Add tree begin symbol to first item if childless
-                       if (tree_procs.front().children.empty())
-                               
tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size()
 - 8, 8, " ┌─ ");
-
-                       //? Add tree terminator symbol to last item if childless
-                       if (tree_procs.back().children.empty())
-                               
tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size()
 - 8, 8, " └─ ");
+                       //? Recursive construction of ASCII tree prefixes.
+                       for (auto t = tree_procs.begin(); t != 
tree_procs.end(); ++t) {
+                               _collect_prefixes(*t, t == tree_procs.end() - 
1);
+                       }
 
                        //? Final sort based on tree index
                        rng::sort(current_procs, rng::less{}, & 
proc_info::tree_index);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/src/linux/btop_collect.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/linux/btop_collect.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/linux/btop_collect.cpp       
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/linux/btop_collect.cpp       
2025-09-10 17:49:55.000000000 +0200
@@ -54,6 +54,7 @@
        #undef class
 #endif
 
+using std::abs;
 using std::clamp;
 using std::cmp_greater;
 using std::cmp_less;
@@ -77,6 +78,18 @@
 using namespace std::chrono_literals;
 //? --------------------------------------------------- FUNCTIONS 
-----------------------------------------------------
 
+namespace
+{
+
+long long get_monotonicTimeUSec()
+{
+       struct timespec time;
+       clock_gettime(CLOCK_MONOTONIC, &time);
+       return time.tv_sec * 1000000 + time.tv_nsec / 1000;
+}
+
+}
+
 namespace Cpu {
        vector<long long> core_old_totals;
        vector<long long> core_old_idles;
@@ -86,6 +99,7 @@
        fs::path freq_path = 
"/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq";
        bool got_sensors{};
        bool cpu_temp_only{};
+       bool supports_watts = true;
 
        //* Populate found_sensors map
        bool get_sensors();
@@ -150,6 +164,8 @@
                nvmlReturn_t (*nvmlDeviceGetTemperature)(nvmlDevice_t, 
nvmlTemperatureSensors_t, unsigned int*);
                nvmlReturn_t (*nvmlDeviceGetMemoryInfo)(nvmlDevice_t, 
nvmlMemory_t*);
                nvmlReturn_t (*nvmlDeviceGetPcieThroughput)(nvmlDevice_t, 
nvmlPcieUtilCounter_t, unsigned int*);
+               nvmlReturn_t (*nvmlDeviceGetEncoderUtilization)(nvmlDevice_t, 
unsigned int*, unsigned int*);
+               nvmlReturn_t (*nvmlDeviceGetDecoderUtilization)(nvmlDevice_t, 
unsigned int*, unsigned int*);
 
                //? Data
                void* nvml_dl_handle;
@@ -307,6 +323,7 @@
                        for (size_t i = 0; i < gpu_b_height_offsets.size(); ++i)
                                gpu_b_height_offsets[i] = 
gpus[i].supported_functions.gpu_utilization
                                           + 
gpus[i].supported_functions.pwr_usage
+                                          + 
(gpus[i].supported_functions.encoder_utilization or 
gpus[i].supported_functions.decoder_utilization)
                                           + 
(gpus[i].supported_functions.mem_total or gpus[i].supported_functions.mem_used)
                                                * (1 + 
2*(gpus[i].supported_functions.mem_total and 
gpus[i].supported_functions.mem_used) + 
2*gpus[i].supported_functions.mem_utilization);
                }
@@ -765,21 +782,21 @@
                //? Try to get battery percentage
                if (percent < 0) {
                        try {
-                               percent = stoll(readfile(b.base_dir / 
"capacity", "-1"));
+                               percent = stoi(readfile(b.base_dir / 
"capacity", "-1"));
                        }
                        catch (const std::invalid_argument&) { }
                        catch (const std::out_of_range&) { }
                }
                if (b.use_energy_or_charge and percent < 0) {
                        try {
-                               percent = round(100.0 * 
stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1")));
+                               percent = round(100.0 * 
stod(readfile(b.energy_now, "-1")) / stod(readfile(b.energy_full, "1")));
                        }
                        catch (const std::invalid_argument&) { }
                        catch (const std::out_of_range&) { }
                }
                if (b.use_energy_or_charge and percent < 0) {
                        try {
-                               percent = round(100.0 * 
stoll(readfile(b.charge_now, "-1")) / stoll(readfile(b.charge_full, "1")));
+                               percent = round(100.0 * 
stod(readfile(b.charge_now, "-1")) / stod(readfile(b.charge_full, "1")));
                        }
                        catch (const std::invalid_argument&) { }
                        catch (const std::out_of_range&) { }
@@ -803,14 +820,14 @@
                        if (b.use_energy_or_charge ) {
                                if (not b.power_now.empty()) {
                                        try {
-                                               seconds = 
round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, 
"1")) * 3600);
+                                               seconds = 
abs(round(stod(readfile(b.energy_now, "0")) / stod(readfile(b.power_now, "1")) 
* 3600));
                                        }
                                        catch (const std::invalid_argument&) { }
                                        catch (const std::out_of_range&) { }
                                }
                                else if (not b.current_now.empty()) {
                                        try {
-                                               seconds = 
round((double)stoll(readfile(b.charge_now, "0")) / 
(double)stoll(readfile(b.current_now, "1")) * 3600);
+                                               seconds = 
abs(round(stod(readfile(b.charge_now, "0")) / stod(readfile(b.current_now, 
"1")) * 3600));
                                        }
                                        catch (const std::invalid_argument&) { }
                                        catch (const std::out_of_range&) { }
@@ -824,20 +841,41 @@
                                catch (const std::invalid_argument&) { }
                                catch (const std::out_of_range&) { }
                        }
-               }
+               } 
+               //? Or get seconds to full
+               else if(is_in(status, "charging")) {
+                       if (b.use_energy_or_charge ) {
+                               if (not b.power_now.empty()) {
+                                       try {
+                                               seconds = 
(round(stod(readfile(b.energy_full , "0")) - round(stod(readfile(b.energy_now, 
"0"))))  
+                                                                       / 
abs(stod(readfile(b.power_now, "1"))) * 3600);
+                                       }
+                                       catch (const std::invalid_argument&) { }
+                                       catch (const std::out_of_range&) { }
+                               }
+                               else if (not b.current_now.empty()) {
+                                       try {
+                                               seconds = 
(round(stod(readfile(b.charge_full , "0")) - stod(readfile(b.charge_now, "0"))) 
 
+                                                                       / 
std::abs(stod(readfile(b.current_now, "1"))) * 3600);
+                                       }
+                                       catch (const std::invalid_argument&) { }
+                                       catch (const std::out_of_range&) { }
+                               }
+                       }
+               } 
 
                //? Get power draw
                if (b.use_power) {
                        if (not b.power_now.empty()) {
                                try {
-                                       watts = 
(float)stoll(readfile(b.power_now, "-1")) / 1000000.0;
+                                       watts = stof(readfile(b.power_now, 
"-1")) / 1000000.0F;
                                }
                                catch (const std::invalid_argument&) { }
                                catch (const std::out_of_range&) { }
                        }
                        else if (not b.voltage_now.empty() and not 
b.current_now.empty()) {
                                try {
-                                       watts = 
(float)stoll(readfile(b.current_now, "-1")) / 1000000.0 * 
stoll(readfile(b.voltage_now, "1")) / 1000000.0;
+                                       watts = stof(readfile(b.current_now, 
"-1")) / 1000000.0F * stof(readfile(b.voltage_now, "1")) / 1000000.0F;
                                }
                                catch (const std::invalid_argument&) { }
                                catch (const std::out_of_range&) { }
@@ -848,6 +886,47 @@
                return {percent, watts, seconds, status};
        }
 
+       long long get_cpuConsumptionUJoules()
+       {
+               long long consumption = -1;
+               const auto rapl_power_usage_path = 
"/sys/class/powercap/intel-rapl:0/energy_uj";
+               std::ifstream file(rapl_power_usage_path);
+               if(file.good())
+               {
+                       file >> consumption;
+               }
+               return consumption;
+       }
+
+       float get_cpuConsumptionWatts()
+       {
+               static long long previous_usage = 0;
+               static long long previous_timestamp = 0;
+
+               if (previous_usage == 0)
+               {
+                       previous_usage = get_cpuConsumptionUJoules();
+                       previous_timestamp = get_monotonicTimeUSec();
+                       supports_watts = (previous_usage > 0);
+                       return 0;
+               }
+
+               if (!supports_watts)
+               {
+                       return -1;
+               }
+
+               auto current_timestamp = get_monotonicTimeUSec();
+               auto current_usage = get_cpuConsumptionUJoules();
+
+               auto watts = (float)(current_usage - previous_usage) / 
(float)(current_timestamp - previous_timestamp);
+
+               previous_timestamp = current_timestamp;
+               previous_usage = current_usage;
+
+               return watts;
+       }
+
        auto collect(bool no_update) -> cpu_info& {
                if (Runner::stopping or (no_update and not 
current_cpu.cpu_percent.at("total").empty())) return current_cpu;
                auto& cpu = current_cpu;
@@ -985,6 +1064,9 @@
                if (Config::getB("show_battery") and has_battery)
                        current_bat = get_battery();
 
+               if (Config::getB("show_cpu_watts") and supports_watts)
+                       current_cpu.usage_watts = get_cpuConsumptionWatts();
+
                return cpu;
        }
 }
@@ -1040,6 +1122,8 @@
                    LOAD_SYM(nvmlDeviceGetTemperature);
                    LOAD_SYM(nvmlDeviceGetMemoryInfo);
                    LOAD_SYM(nvmlDeviceGetPcieThroughput);
+                       LOAD_SYM(nvmlDeviceGetEncoderUtilization);
+                       LOAD_SYM(nvmlDeviceGetDecoderUtilization);
 
             #undef LOAD_SYM
 
@@ -1095,7 +1179,7 @@
                                result = nvmlDeviceGetHandleByIndex(i, 
devices.data() + i);
                                if (result != NVML_SUCCESS) {
                                        Logger::warning(std::string("NVML: 
Failed to get device handle: ") + nvmlErrorString(result));
-                                       gpus[i].supported_functions = {false, 
false, false, false, false, false, false, false};
+                                               gpus[i].supported_functions = 
{false, false, false, false, false, false, false, false, false, false};
                                        continue;
                                }
 
@@ -1242,6 +1326,30 @@
                                        }
                                }
 
+                               // nvTimer.stop_rename_reset("Nv enc");
+                               //? Encoder info
+                               if 
(gpus_slice[i].supported_functions.encoder_utilization) {
+                                       unsigned int utilization;
+                                       unsigned int samplingPeriodUs;
+                                       result = 
nvmlDeviceGetEncoderUtilization(devices[i], &utilization, &samplingPeriodUs);
+                                       if (result != NVML_SUCCESS) {
+                                               
Logger::warning(std::string("NVML: Failed to get encoder utilization: ") + 
nvmlErrorString(result));
+                                               if constexpr(is_init) 
gpus_slice[i].supported_functions.encoder_utilization = false;
+                                       } else 
gpus_slice[i].encoder_utilization = (long long)utilization;
+                               }
+
+                               // nvTimer.stop_rename_reset("Nv dec");
+                               //? Decoder info
+                               if 
(gpus_slice[i].supported_functions.decoder_utilization) {
+                                       unsigned int utilization;
+                                       unsigned int samplingPeriodUs;
+                                       result = 
nvmlDeviceGetDecoderUtilization(devices[i], &utilization, &samplingPeriodUs);
+                                       if (result != NVML_SUCCESS) {
+                                               
Logger::warning(std::string("NVML: Failed to get decoder utilization: ") + 
nvmlErrorString(result));
+                                               if constexpr(is_init) 
gpus_slice[i].supported_functions.decoder_utilization = false;
+                                       } else 
gpus_slice[i].decoder_utilization = (long long)utilization;
+                               }
+
                        //? TODO: Processes using GPU
                                /*unsigned int proc_info_len;
                                nvmlProcessInfo_t* proc_info = 0;
@@ -1415,6 +1523,10 @@
                                if (result != RSMI_STATUS_SUCCESS)
                                        Logger::warning("ROCm SMI: Failed to 
get maximum GPU temperature, defaulting to 110°C");
                                else gpus_slice[i].temp_max = (long 
long)temp_max;
+
+                                       //? Disable encoder and decoder 
utilisation on AMD
+                                       
gpus_slice[i].supported_functions.encoder_utilization = false;
+                                       
gpus_slice[i].supported_functions.decoder_utilization = false;
                        }
 
                                //? GPU utilization
@@ -1646,7 +1758,9 @@
                                        .temp_info = false,
                                        .mem_total = false,
                                        .mem_used = false,
-                                       .pcie_txrx = false
+                                       .pcie_txrx = false,
+                                       .encoder_utilization = false,
+                                       .decoder_utilization = false
                                };
 
                                gpus_slice->pwr_max_usage = 10'000; //? 10W
@@ -1738,6 +1852,36 @@
 }
 #endif
 
+/// Convert ascii escapes like \040 into chars.
+static auto convert_ascii_escapes(const std::string& input) -> std::string {
+    std::string out;
+    out.reserve(input.size());
+
+    for (std::size_t i = 0; i < input.size(); ++i) {
+        if (input[i] == '\\' &&
+               // Peek the next three characters.
+            i + 3 < input.size() &&
+            std::isdigit(input[i + 1]) &&
+            std::isdigit(input[i + 2]) &&
+            std::isdigit(input[i + 3])) {
+
+                       // Convert octal chars to decimal int.
+                       //   '0' - '0' -> 0, '4' - '0' -> 4, '0' - '0' -> 0.
+                       //   0 * 64 (0)
+                       //   + 4 * 8 (32)
+                       //   + 0
+                       //   = 32 (ascii space)
+            int value = ((input[i + 1] - '0') * 64) + ((input[i + 2] - '0') * 
8) + (input[i + 3] - '0');
+            out.push_back(static_cast<char>(value));
+            // Consume the three digits.
+            i += 3;
+        } else {
+            out.push_back(input[i]);
+        }
+    }
+    return out;
+}
+
 namespace Mem {
        bool has_swap{};
        vector<string> fstab;
@@ -1923,17 +2067,22 @@
                                        diskread.close();
                                }
 
-                               //? Get mounts from /etc/mtab or 
/proc/self/mounts
-                               diskread.open((fs::exists("/etc/mtab") ? 
fs::path("/etc/mtab") : Shared::procPath / "self/mounts"));
+                               //? Get mounts from /proc/self/mountinfo
+                               diskread.open((Shared::procPath / 
"self/mountinfo"));
                                if (diskread.good()) {
                                        vector<string> found;
                                        found.reserve(last_found.size());
-                                       string dev, mountpoint, fstype;
+                                       string dev, major_minor, mountpoint, 
fstype, _;
                                        while (not diskread.eof()) {
+                                               // See proc_pid_mountinfo(5) 
for the file format
+                                               // We specifically want the 
major/minor device numbers
                                                std::error_code ec;
-                                               diskread >> dev >> mountpoint 
>> fstype;
+                                               diskread >> _ >> _ >> 
major_minor >> _ >> mountpoint >> _ >> _ >> _ >> fstype >> dev >> _;
                                                diskread.ignore(SSmax, '\n');
 
+                                               // A mountpoint can ascii 
escape codes, which will not work with `statvfs`.
+                                               mountpoint = 
convert_ascii_escapes(mountpoint);
+
                                                if (v_contains(ignore_list, 
mountpoint) or v_contains(found, mountpoint)) continue;
 
                                                //? Match filter if not empty
@@ -1961,25 +2110,17 @@
                                                                        if 
(mountpoint == "/mnt") disks.at(mountpoint).name = "root";
                                                                #endif
                                                                if 
(disks.at(mountpoint).name.empty()) disks.at(mountpoint).name = (mountpoint == 
"/" ? "root" : mountpoint);
-                                                               string devname 
= disks.at(mountpoint).dev.filename();
-                                                               int c = 0;
-                                                               while 
(devname.size() >= 2) {
-                                                                       if 
(fs::exists("/sys/block/" + devname + "/stat", ec) and 
access(string("/sys/block/" + devname + "/stat").c_str(), R_OK) == 0) {
-                                                                               
if (c > 0 and fs::exists("/sys/block/" + devname + '/' + 
disks.at(mountpoint).dev.filename().string() + "/stat", ec))
-                                                                               
        disks.at(mountpoint).stat = "/sys/block/" + devname + '/' + 
disks.at(mountpoint).dev.filename().string() + "/stat";
-                                                                               
else
-                                                                               
        disks.at(mountpoint).stat = "/sys/block/" + devname + "/stat";
-                                                                               
break;
+
+                                                               // Use the 
major:minor device numbers to get device stats; see sysfs(5)
+                                                               auto stat_path 
= "/sys/dev/block/" + major_minor + "/stat";
+                                                               if 
(fs::exists(stat_path, ec) and access(stat_path.c_str(), R_OK) == 0) {
+                                                                       
disks.at(mountpoint).stat = stat_path;
+                                                               } else if 
(fstype == "zfs") {
                                                                        //? Set 
ZFS stat filepath
-                                                                       } else 
if (fstype == "zfs") {
-                                                                               
disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, 
zfs_hide_datasets);
-                                                                               
if (disks.at(mountpoint).stat.empty()) {
-                                                                               
        Logger::debug("Failed to get ZFS stat file for device " + dev);
-                                                                               
}
-                                                                               
break;
+                                                                       
disks.at(mountpoint).stat = get_zfs_stat_file(dev, zfs_dataset_name_start, 
zfs_hide_datasets);
+                                                                       if 
(disks.at(mountpoint).stat.empty()) {
+                                                                               
Logger::debug("Failed to get ZFS stat file for device " + dev);
                                                                        }
-                                                                       
devname.resize(devname.size() - 1);
-                                                                       c++;
                                                                }
                                                        }
 
@@ -2006,7 +2147,7 @@
                                        last_found = std::move(found);
                                }
                                else
-                                       throw std::runtime_error("Failed to get 
mounts from /etc/mtab and /proc/self/mounts");
+                                       throw std::runtime_error("Failed to get 
mounts from /proc/self/mountinfo");
                                diskread.close();
 
                                //? Get disk/partition stats
@@ -2399,7 +2540,7 @@
                                        auto& bandwidth = 
netif.bandwidth.at(dir);
 
                                        uint64_t val{};
-                                       try { val = 
(uint64_t)stoull(readfile(sys_file, "0")); }
+                                       try { val = stoull(readfile(sys_file, 
"0")); }
                                        catch (const std::invalid_argument&) {}
                                        catch (const std::out_of_range&) {}
 
@@ -2974,13 +3115,10 @@
                        int index = 0;
                        tree_sort(tree_procs, sorting, reverse, index, 
current_procs.size());
 
-                       //? Add tree begin symbol to first item if childless
-                       if (tree_procs.size() > 0 and 
tree_procs.front().children.empty() and 
tree_procs.front().entry.get().prefix.size() >= 8)
-                               
tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size()
 - 8, 8, " ┌─ ");
-
-                       //? Add tree terminator symbol to last item if childless
-                       if (tree_procs.size() > 0 and 
tree_procs.back().children.empty() and 
tree_procs.back().entry.get().prefix.size() >= 8)
-                               
tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size()
 - 8, 8, " └─ ");
+                       //? Recursive construction of ASCII tree prefixes.
+                       for (auto t = tree_procs.begin(); t != 
tree_procs.end(); ++t) {
+                               _collect_prefixes(*t, t == tree_procs.end() - 
1);
+                       }
 
                        //? Final sort based on tree index
                        rng::sort(current_procs, rng::less{}, & 
proc_info::tree_index);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/src/netbsd/btop_collect.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/netbsd/btop_collect.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/netbsd/btop_collect.cpp      
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/netbsd/btop_collect.cpp      
2025-09-10 17:49:55.000000000 +0200
@@ -84,7 +84,7 @@
        vector<string> available_fields = {"total"};
        vector<string> available_sensors = {"Auto"};
        cpu_info current_cpu;
-       bool got_sensors = false, cpu_temp_only = false;
+       bool got_sensors = false, cpu_temp_only = false, supports_watts = false;
 
        //* Populate found_sensors map
        bool get_sensors();
@@ -1346,13 +1346,10 @@
                        int index = 0;
                        tree_sort(tree_procs, sorting, reverse, index, 
current_procs.size());
 
-                       //? Add tree begin symbol to first item if childless
-                       if (tree_procs.front().children.empty())
-                               
tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size()
 - 8, 8, " ┌─ ");
-
-                       //? Add tree terminator symbol to last item if childless
-                       if (tree_procs.back().children.empty())
-                               
tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size()
 - 8, 8, " └─ ");
+                       //? Recursive construction of ASCII tree prefixes.
+                       for (auto t = tree_procs.begin(); t != 
tree_procs.end(); ++t) {
+                               _collect_prefixes(*t, t == tree_procs.end() - 
1);
+                       }
 
                        //? Final sort based on tree index
                        rng::sort(current_procs, rng::less{}, & 
proc_info::tree_index);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/src/openbsd/btop_collect.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/openbsd/btop_collect.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/openbsd/btop_collect.cpp     
2025-07-18 00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/openbsd/btop_collect.cpp     
2025-09-10 17:49:55.000000000 +0200
@@ -83,7 +83,7 @@
        vector<string> available_fields = {"total"};
        vector<string> available_sensors = {"Auto"};
        cpu_info current_cpu;
-       bool got_sensors = false, cpu_temp_only = false;
+       bool got_sensors = false, cpu_temp_only = false, supports_watts = false;
 
        //* Populate found_sensors map
        bool get_sensors();
@@ -1198,13 +1198,10 @@
                        int index = 0;
                        tree_sort(tree_procs, sorting, reverse, index, 
current_procs.size());
 
-                       //? Add tree begin symbol to first item if childless
-                       if (tree_procs.front().children.empty())
-                               
tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size()
 - 8, 8, " ┌─ ");
-
-                       //? Add tree terminator symbol to last item if childless
-                       if (tree_procs.back().children.empty())
-                               
tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size()
 - 8, 8, " └─ ");
+                       //? Recursive construction of ASCII tree prefixes.
+                       for (auto t = tree_procs.begin(); t != 
tree_procs.end(); ++t) {
+                               _collect_prefixes(*t, t == tree_procs.end() - 
1);
+                       }
 
                        //? Final sort based on tree index
                        rng::sort(current_procs, rng::less{}, & 
proc_info::tree_index);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/btop-1.4.4+git20250718.86ec5fd/src/osx/btop_collect.cpp 
new/btop-1.4.4+git20250910.bdddfc4/src/osx/btop_collect.cpp
--- old/btop-1.4.4+git20250718.86ec5fd/src/osx/btop_collect.cpp 2025-07-18 
00:20:18.000000000 +0200
+++ new/btop-1.4.4+git20250910.bdddfc4/src/osx/btop_collect.cpp 2025-09-10 
17:49:55.000000000 +0200
@@ -77,7 +77,7 @@
        vector<string> available_fields = {"Auto", "total"};
        vector<string> available_sensors = {"Auto"};
        cpu_info current_cpu;
-       bool got_sensors = false, cpu_temp_only = false;
+       bool got_sensors = false, cpu_temp_only = false, supports_watts = false;
        int core_offset = 0;
 
        //* Populate found_sensors map
@@ -1337,13 +1337,10 @@
                        int index = 0;
                        tree_sort(tree_procs, sorting, reverse, index, 
current_procs.size());
 
-                       //? Add tree begin symbol to first item if childless
-                       if (tree_procs.front().children.empty())
-                               
tree_procs.front().entry.get().prefix.replace(tree_procs.front().entry.get().prefix.size()
 - 8, 8, " ┌─ ");
-
-                       //? Add tree terminator symbol to last item if childless
-                       if (tree_procs.back().children.empty())
-                               
tree_procs.back().entry.get().prefix.replace(tree_procs.back().entry.get().prefix.size()
 - 8, 8, " └─ ");
+                       //? Recursive construction of ASCII tree prefixes.
+                       for (auto t = tree_procs.begin(); t != 
tree_procs.end(); ++t) {
+                               _collect_prefixes(*t, t == tree_procs.end() - 
1);
+                       }
 
                        //? Final sort based on tree index
                        rng::sort(current_procs, rng::less{}, & 
proc_info::tree_index);

++++++ btop.obsinfo ++++++
--- /var/tmp/diff_new_pack.K2fSxJ/_old  2025-09-22 19:29:19.925979836 +0200
+++ /var/tmp/diff_new_pack.K2fSxJ/_new  2025-09-22 19:29:19.929980004 +0200
@@ -1,5 +1,5 @@
 name: btop
-version: 1.4.4+git20250718.86ec5fd
-mtime: 1752790818
-commit: 86ec5fd06282a96ae46542e653490b7144e801f9
+version: 1.4.4+git20250910.bdddfc4
+mtime: 1757519395
+commit: bdddfc46a2bbfe4ba70c7fba4fbb30978d61dab9
 

Reply via email to