Skip to content

fix: show ethernet connection in network widget#2426

Open
ultherego wants to merge 9 commits intonoctalia-dev:mainfrom
ultherego:feature/network-widget
Open

fix: show ethernet connection in network widget#2426
ultherego wants to merge 9 commits intonoctalia-dev:mainfrom
ultherego:feature/network-widget

Conversation

@ultherego
Copy link
Copy Markdown

Pull Request

If this PR is not ready for review yet, please mark it as Draft until it's good to be reviewed.

Motivation

Fix Ethernet connection not being displayed in the network widget after recent networking changes. The issue occurs even when a wired connection is active and working correctly.

Type of Change

Mark the relevant option with an "x".

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring

Related Issue

Testing

Describe how you tested your changes and mark the relevant items.

  • Tested on niri
  • Tested on Hyprland
  • Tested on sway
  • Tested with different bar positions and density settings
  • Tested at different interface scaling values
  • Tested with multiple monitors (if applicable)

Screenshots / Videos

obraz obraz obraz

Checklist

  • Code follows project style guidelines
  • Self-reviewed my code
  • No new warnings or errors
  • Documentation or comments updated (if relevant)

Additional Notes

This change restores Ethernet (wired) connection visibility in the network widget while keeping existing Wi-Fi behavior unchanged.
Handles wired connections from NetworkManager and ensures they are properly reflected in the widget state.

}
}

NBox {
Copy link
Copy Markdown
Contributor

@notiant notiant Apr 8, 2026

Choose a reason for hiding this comment

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

The layout of the box needs some rework:

Image

should have the same margins and centering as ethernet:

Image

The left and right margins of the VPN connections in you screenshot are also different from wifi/ethernet

Comment thread Modules/Panels/Network/NetworkPanel.qml Outdated
Item {
Layout.fillHeight: true
}
Item { Layout.fillHeight: true }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This format change is out of style with the rest of the code. Also not sure why you are deleting so many comments

// Mode switch (Wi‑Fi / Ethernet)
NTabBar {
id: modeTabBar
visible: NetworkService.ethernetAvailable && NetworkService.wifiAvailable
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not a fan of having the tab bar always visible. I only use the widget for wifi and have no ethernet port, so this seems like unnecessary clutter.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I agree with that, I don't have Wi-Fi and it's visible in the widget. In this case, anything not in use should be hidden.

Copy link
Copy Markdown
Contributor

@turannul turannul Apr 9, 2026

Choose a reason for hiding this comment

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

I agree with that, I don't have Wi-Fi and it's visible in the widget. In this case, anything not in use should be hidden.

It was the default before i even involved in it, i kept it as is.
not my skill issue this time 😃

Though this tab bar can be better

maybe (wifi || eth) && vpn

Comment thread Modules/Panels/Network/NetworkPanel.qml Outdated
// - If Wi-Fi is actively connected, open Wi-Fi first
// - Otherwise always open Ethernet first
// VPN is manual-only and should not be auto-selected
if (NetworkService.wifiConnected) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This doesn't make sense on devices that have no ethernet port. There is a problem in the current opening logic that the ethernet tab is not shown if ethernet is connected but the last view was Wi-Fi and Wi-Fi is disabled, but this can be solved with this:

  onOpened: {
    // Restore last view if valid, otherwise choose what's available (prefer Wi‑Fi when both exist)
    const last = Settings.data.network.networkPanelView;
    if (NetworkService.ethernetAvailable && (last === "ethernet" || !NetworkService.wifiEnabled)) {
      panelViewMode = "ethernet";
    } else {
      panelViewMode = "wifi";
    }
    panelViewPersistEnabled = true;
  }

@ultherego
Copy link
Copy Markdown
Author

ultherego commented Apr 9, 2026

How it currently works:

  1. The Wi-Fi tab is visible when NetworkService.wifiAvailable is true — that is, when a Wi-Fi adapter/interface exists in the system (e.g., wlan0). This property comes from NetworkService.qml, which sets _wifiAvailable = true when nmcli device finds a device of type wifi.

The tab is always primary.

  1. The Ethernet tab is visible when NetworkService.ethernetAvailable is true — that is, when a physical Ethernet interface exists in the system (e.g., eth0, enp3s0). Similar to Wi-Fi, it is detected via nmcli device as a device of type ethernet.

The tab is visible, but launching the widget automatically sets Wi-Fi as primary.
If Wi-Fi is OFF (via the switch), it sets Ethernet as primary.

  1. The VPN tab is visible when root.vpnAvailable is true — that is, when Object.keys(VPNService.connections).length > 0, in other words, when at least one VPN connection is configured in NetworkManager (e.g., WireGuard, OpenVPN).

This is a different condition than Wi-Fi/Ethernet — those depend on the presence of a physical adapter, while VPN depends on the presence of a configuration (connection profile).

Comment thread Modules/Panels/Network/NetworkPanel.qml Outdated
Comment on lines +30 to +39
// Whether VPN configurations exist (tab only shown when true)
readonly property bool vpnAvailable: Object.keys(VPNService.connections).length > 0

// If VPN configs vanish while on VPN tab, switch away
onVpnAvailableChanged: {
if (!vpnAvailable && panelViewMode === "vpn") {
panelViewMode = NetworkService.wifiAvailable ? "wifi" : "ethernet";
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This would supposed to be in VPNService?

Retrieved/used within connections block or if (VPNService.x)

Comment thread Modules/Panels/Network/NetworkPanel.qml Outdated
} else {
panelViewMode = "wifi";
}
panelViewMode = "wifi"; // fallback (shows empty/disabled state)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

On a second thought wifi as fallback questionable choice.
Do you think ethernet fits better?

Comment thread Modules/Panels/Network/NetworkPanel.qml Outdated

// VPN empty state
NBox {
visible: panelViewMode === "vpn" && Object.keys(VPNService.connections).length === 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I cannot try atm and rest of the day.

But have a question, empty view of vpn has no purpose i can think of...

@turannul
Copy link
Copy Markdown
Contributor

turannul commented Apr 9, 2026

How it currently works:

  1. The Wi-Fi tab is visible when NetworkService.wifiAvailable is true — that is, when a Wi-Fi adapter/interface exists in the system (e.g., wlan0). This property comes from NetworkService.qml, which sets _wifiAvailable = true when nmcli device finds a device of type wifi.

The tab is always primary.

  1. The Ethernet tab is visible when NetworkService.ethernetAvailable is true — that is, when a physical Ethernet interface exists in the system (e.g., eth0, enp3s0). Similar to Wi-Fi, it is detected via nmcli device as a device of type ethernet.

The tab is visible, but launching the widget automatically sets Wi-Fi as primary.

If Wi-Fi is OFF (via the switch), it sets Ethernet as primary.

  1. The VPN tab is visible when root.vpnAvailable is true — that is, when Object.keys(VPNService.connections).length > 0, in other words, when at least one VPN connection is configured in NetworkManager (e.g., WireGuard, OpenVPN).

This is a different condition than Wi-Fi/Ethernet — those depend on the presence of a physical adapter, while VPN depends on the presence of a configuration (connection profile).

If you want to dig further i do not tried vpns on linux/network manager
but macOS threated like virtual interface only if thats the case here.

we may can use deviceStatusProcess would super-seed entire VPNService :P
with none to minimum effort

Honestly l don't know why i didn't do/tried doing this before.

Copy link
Copy Markdown
Contributor

@turannul turannul left a comment

Choose a reason for hiding this comment

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

Looks good to me

@ultherego
Copy link
Copy Markdown
Author

How it currently works:

  1. The Wi-Fi tab is visible when NetworkService.wifiAvailable is true — that is, when a Wi-Fi adapter/interface exists in the system (e.g., wlan0). This property comes from NetworkService.qml, which sets _wifiAvailable = true when nmcli device finds a device of type wifi.

The tab is always primary.

  1. The Ethernet tab is visible when NetworkService.ethernetAvailable is true — that is, when a physical Ethernet interface exists in the system (e.g., eth0, enp3s0). Similar to Wi-Fi, it is detected via nmcli device as a device of type ethernet.

The tab is visible, but launching the widget automatically sets Wi-Fi as primary.
If Wi-Fi is OFF (via the switch), it sets Ethernet as primary.

  1. The VPN tab is visible when root.vpnAvailable is true — that is, when Object.keys(VPNService.connections).length > 0, in other words, when at least one VPN connection is configured in NetworkManager (e.g., WireGuard, OpenVPN).

This is a different condition than Wi-Fi/Ethernet — those depend on the presence of a physical adapter, while VPN depends on the presence of a configuration (connection profile).

If you want to dig further i do not tried vpns on linux/network manager but macOS threated like virtual interface only if thats the case here.

we may can use deviceStatusProcess would super-seed entire VPNService :P with none to minimum effort

Honestly l don't know why i didn't do/tried doing this before.

Tested it — NM does create virtual interfaces (tun0 for OpenVPN, wg0 for WireGuard), and deviceStatusProcess sees them. However it can't replace VPNService because the interface only exists while VPN is active. Inactive VPN configs are invisible to nmcli device show:

# VPN inactive — device show has no trace of VPN:
❯ nmcli -t -f GENERAL.DEVICE,GENERAL.TYPE device show
GENERAL.DEVICE:enp5s0
GENERAL.TYPE:ethernet

# VPN active — tun0 appears but name is "tun0", not the VPN name:
❯ nmcli -t -f GENERAL.DEVICE,GENERAL.TYPE,GENERAL.CONNECTION device show tun0
GENERAL.DEVICE:tun0
GENERAL.TYPE:tun
GENERAL.CONNECTION:tun0

# Only connection show knows VPN configs and names:
❯ nmcli -t -f NAME,UUID,TYPE connection show | grep vpn
My VPN 1:xxxxxxxx-...:vpn:
My VPN 2:yyyyyyyy-...:vpn:

So deviceStatusProcess could complement VPNService (detect active VPN state, IP, DNS for bar icon etc.) but can't supersede it — we still need nmcli connection show for the list of available VPNs and connect/disconnect.

panelViewMode = "wifi";
} else if (NetworkService.ethernetAvailable) {
panelViewMode = "ethernet";
} else if (VPNService.hasConnections) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There needs to be an additional NetworkService.wifiAvailable check after the VPN check; if I disable wifi it opens the ethernet panel for me and i can't use the panel to enable wifi again!
Also, if you are removing the use of Settings.data.network.networkPanelView you should delete all references to it and panelViewPersistEnabled in the code. Settings have to be removed from settings.qml and settings-default.json as well.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good points, thanks for checking. I’ll push the fixes over the weekend and try to analyze it.

Additionally, I encountered an issue myself:

The widget was constantly enabled
I unplugged the Wi-Fi USB
I received a notification about it being unavailable
I plugged the Wi-Fi USB back in — the Wi-Fi unavailable view remained; only reopening the widget updated it

Comment thread Services/Networking/NetworkService.qml Outdated
}

Timer {
id: _monitorDebounce
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We do need this? onRead only triggers when nmcli prints

Comment thread Services/Networking/NetworkService.qml Outdated
_monitorDebounce.stop();
deviceStatusProcess.running = true;
connectivityCheckProcess.running = true;
} else if (data.endsWith(": unavailable") || data.endsWith(": unmanaged") || data.indexOf(": device removed") !== -1 || data.indexOf(": device created") !== -1) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should not bother with unmanaged devices.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I was in the process of checking what else was left to remove, etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looking for something to remove? - See this

Was replacing Processes with quickshell API/Methods. - Whats left atm connectProcess

Copy link
Copy Markdown

@dinhokusanagi dinhokusanagi left a comment

Choose a reason for hiding this comment

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

Tested this PR locally using Nix.

Environment:

  • Wayland (Hyprland)

Results:

  • Build: OK
  • Runs: OK
  • No crashes observed
  • Feature behaves as expected

Notes:

  • Tested basic usage and interactions
  • No regressions observed

Screenshot attached.

2026-04-18-190227_hyprshot

@notiant
Copy link
Copy Markdown
Contributor

notiant commented Apr 19, 2026

There are some layout problems with the current version, in part because you copied from the ethernet layout which also has problems (the reference layout at the moment is the Wi-Fi view). Since there are a lot of changes, I've edited the current NetworkPanel.qml in your PR and pasted it here: https://pastebin.com/bmQdvaJP

Another issue is the refreshTimer in VPNService. I don't think it's necessary to run this every 5s as a background process and would remove the timer completely.
Just seeing that this wasn't added by you and is probably necessary for the VPN widget. Not sure if it's the best implementation though.

@ultherego
Copy link
Copy Markdown
Author

ultherego commented Apr 19, 2026

Thank you for taking a look at this.

Polling the VPN every 5 seconds doesn’t make sense — that’s what the refresh button is for.
I’ll take another look at the 5s interval, because from what I remember and from reviewing the code, the refreshTimer is only triggered in the following situations:

  • Component.onCompleted — once at startup
  • NetworkPanel.onPanelViewModeChanged — when the user switches to the VPN tab
  • NetworkPanel.onEffectivelyVisibleChanged — when the panel is opened
  • scheduleRefresh() — after connect/disconnect/refresh (1–2s delay)
  • Refresh button in the panel

Another thing: I see you changed the logic of the connect/disconnect button in the VPN. I’m not sure if that’s a good idea, because they disappear for all items while they’re being used. Sometimes someone connects to several at once and just clicks connect/disconnect on selected ones simultaneously (it’s more about convenience than necessity).

The rest of the changes seem reasonable to me, thanks a lot 👍

@notiant
Copy link
Copy Markdown
Contributor

notiant commented Apr 19, 2026

Thank you for taking a look at this.

Polling the VPN every 5 seconds doesn’t make sense — that’s what the refresh button is for. Another thing: I see you changed the logic of the connect/disconnect button in the VPN. I’m not sure if that’s a good idea, because they disappear for all items while they’re being used. Sometimes someone connects to several at once and just clicks connect/disconnect on selected ones simultaneously (it’s more about convenience than necessity).

The rest of the changes seem reasonable to me, thanks a lot 👍

The connect/disconnect button only disappear for the VPN connection that's currently connecting/disconnecting. I've just copied the logic from the Wi-Fi tab. You can keep the enabled property if you want to prevent that people can connect to another VPN while there is a connect process ongoing.

For the VPN refresh: There exists a VPN widget for the bar and I think the refreshTimer might be necessary to keep it updated.

…delegates, fix margins and anchors

Apply notiant's layout review: unified getContentColors()/forceOpaque pattern
for ethernet and VPN delegates, consistent margins (marginL/marginM), proper
anchors, removed badge pill. VPN connect/disconnect buttons use enabled (not
visible) to prevent layout jumps while blocking concurrent operations.
@ultherego
Copy link
Copy Markdown
Author

visible: !VPNService.disconnecting && VPNService.disconnectingUuid !== modelData.uuid
!disconnecting is false globally — so both buttons disappear regardless of the UUID.

I changed it to enabled: !VPNService.disconnecting it does the same thing (blocks both), but at least the buttons remain visible and the user can see they’re greyed out instead of disappearing without a trace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ethernet not showing in network widget after latest update

4 participants