1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-23 11:35:25 -04:00

Compare commits

...

100 Commits

Author SHA1 Message Date
bbedward 0e7901ebbe keybinds: fix mouse wheel keysims on Hyprland and Mango
fixes #2683
2026-06-23 11:21:38 -04:00
bbedward 73f3a72d00 sysupdate: fix check scheduling
- deadline-based, fixes the issue before that would reset the interval
  without accounting for prior time waited
2026-06-23 09:55:39 -04:00
bbedward 63feabf517 i18n: add esperonoto and sync 2026-06-23 09:45:19 -04:00
Youseffo13 84f87dd7f3 fix: UI polishes, uptime formatting, and missing i18n strings (#2686)
* Update CompositorLayoutTab.qml

* add missing i18n strings

* fix context menu overflow and strip uptime prefix

* fix settings index

---------

Co-authored-by: bbedward <bbedward@gmail.com>
2026-06-23 09:33:29 -04:00
Ralph Zhou 39c247d9cb fix(lock): add complete bundled PAM services (#2685) 2026-06-23 09:26:51 -04:00
NihilDigit a98c4f6c54 fix(network): show WiFi connection progress (#2684) 2026-06-23 09:19:37 -04:00
bbedward bed6622530 settings: fix index/pre-commit 2026-06-22 23:29:47 -04:00
bbedward c5e08a6f2c core: migrate to mockery v3 2026-06-22 23:27:29 -04:00
purian23 ad32af6eeb settings(dbar): add bar inset padding UI opts in framemode/stanalone
Fixes #2597
2026-06-22 21:10:36 -04:00
bbedward 02ced4b87b notifications: expireTimeout already comes in miliseconds 2026-06-22 15:03:49 -04:00
bbedward 5b28a63f75 portal: add bidirectional syncing with freedesktop color-scheme, read in
addition to the existing write
2026-06-22 14:52:10 -04:00
bbedward b5e2e68a22 greeter: redesign the switch-user/auto-login flow
- Fix visual glitches
- Make auto-login and switch user texts not always visible
- Make from-zero memory state not confusing
2026-06-22 13:50:50 -04:00
bbedward 556c0819c4 core/network: avoid endless probing when no network backend is present 2026-06-22 13:09:04 -04:00
purian23 b0edccb80e fix(greeter): restore legacy remembered sessions by desktop id
- Derive a desktop id from legacy remembered session paths
- Match remembered sessions by desktop id before falling back to path
2026-06-22 12:56:45 -04:00
bbedward 4e1c921ffb notifications: respect expireTimeout set by notifiers 2026-06-22 12:33:51 -04:00
purian23 fdbbcafb6c fix(greeter): avoid pinning auto-login session commands
- Store a desktop session identity instead of relying on raw Exec commands
- Resolve the current session desktop file when auto-login launches
- Preserve legacy memory compatibility while ignoring stale lastSessionExec
- Add regression coverage for stale /nix/store session paths
- Autologin users should rerun the process
2026-06-22 11:34:27 -04:00
Huỳnh Thiện Lộc a043d477fb feat(battery): add options to toggle percentage and remaining time (#2672)
* feat(battery): add options to toggle percentage and remaining time

* fix(battery): add SettingsSpec entries and combine verticalDisplayText

* fix(battery): format vertical battery remaining time as HH\nMM and center alignment

* fix(battery): remove percent sign from vertical layout when time is enabled
2026-06-21 22:12:48 -04:00
Huỳnh Thiện Lộc 4cbe766cbd feat(wallpaper): support configurable background color (#2671)
* feat(wallpaper): support configurable background color

* chore(translations): update settings search index

* revert(wallpaper): keep Pad naming instead of Center
2026-06-21 03:57:08 -04:00
Huỳnh Thiện Lộc 8610b915ec feat: add option to hide package source badges in launcher (#2676) 2026-06-21 03:51:44 -04:00
jbwfu 59fd6db83e Enhance/clipboard history interactions (#2668)
* feat(clipboard): add entry context menu

* feat(clipboard): add click to paste option

* feat(clipboard): add optional copy and paste action buttons

* fix(clipboard): default selection and esc behavior

* fix(clipboard): prevent clear and filter overlap

* Update to remove dead kb nav & add escape action on context menu

---------

Co-authored-by: purian23 <purian23@gmail.com>
2026-06-21 03:50:51 -04:00
purian23 465cf7355b distros(void linux): initial packaging support 2026-06-21 01:21:39 -04:00
bbedward de91b78943 theme/icons: add separate light/dark path, hot-reload, detect external
DMS maangedand reset
fixes #608
closes #2674
2026-06-20 15:23:19 -04:00
bbedward 4203148cab ci: add settings index check to pre-commit 2026-06-18 18:42:33 -04:00
bbedward 5adc0c464a toast: fix blur 2026-06-18 15:49:53 -04:00
Rocho 097290f7da fix(lock): show the faillock lockout reason instead of "incorrect password" (#2669)
When pam_faillock locks the account (DMS authenticates through the system PAM
stack: /etc/pam.d/login -> system-auth), the lock screen kept showing the
generic "Incorrect password - try again" even though the real cause is a
lockout, so a correct password looks rejected and only a reboot (which clears
the tmpfs /run/faillock tally) appears to help. See #2647.

The previous onMessageChanged only matched the *English* faillock strings
("The account is locked ...") and then wiped that text again on the trailing
pam_unix "Password:" prompt. On a non-English system (e.g. German) the strings
never matched, so the lockout was never surfaced at all.

Detect the notice by position rather than by text: pam emits its informational
messages within an attempt before the password prompt. Collect every non-prompt
info message and, once the prompt arrives, surface the collected lines (minus
the prompt itself) as lockMessage. If the stack short-circuits without ever
prompting (e.g. pam_faillock preauth configured as requisite), the notice is
surfaced on completion instead. This is locale-independent. A per-attempt flag
keeps the message stable across repeated locked attempts and retires it when an
attempt completes without a lockout (faillock reset / unlock_time elapsed).

Fixes #2647
2026-06-18 09:54:02 -04:00
Ira Limitanei 475ef5d1ca feat(launcher): make dms color picker entry toggleable (#2667) 2026-06-18 08:46:04 -04:00
Ralph Zhou 2f37019782 fix(popouts): keep Hyprland focus during close (#2655) 2026-06-18 01:41:25 -04:00
Rocho 9f4123cc3c fix(bar): clear blur region when the bar is hidden (auto-hide) (#2658)
When a bar with background transparency + blur uses auto-hide, the
ext-background-effect-v1 blur region was only slid off-surface via the
reveal Translate, but the region object stayed non-empty.

Hyprland gates layer-surface blur on `!m_blurRegion.empty()`, so the
non-empty region keeps blur enabled; the renderer then intersects the
off-surface region with the surface box, the clip degenerates to empty,
and an empty clip is treated as "unclipped" — so the whole bar surface
box gets blurred, leaving a blurred strip where the hidden bar would be.
(niri clips correctly, so it never showed there.)

Gate the published blur region on `barRevealed`: tear it down (null)
whenever the bar is not currently shown, so the region is genuinely
empty and the compositor disables the effect. Fixes #2656.
2026-06-18 00:58:19 -04:00
Yechiel 482a87a80d feat(bar): add visual indication for connected bluetooth (#2662) 2026-06-18 00:57:27 -04:00
jbwfu b925010cb3 fix(clipboard): paste selected history entry (#2660) 2026-06-18 00:57:07 -04:00
Huỳnh Thiện Lộc 085ce01da6 feat: port critical battery alert from DankBatteryAlerts plugin (#2664)
* feat: port critical battery alert from DankBatteryAlerts plugin

* ui: shorten notification type labels

* refactor: remove duplicate battery charge limit from Power & Sleep
2026-06-17 22:14:57 -04:00
Jonas Bloch 7af530de8f fix(ui): use primaryText instead of primary for text and icons displayed on primaryContainer background in the launcher (#2586)
* fix(ui): use primaryText instead of primary for text and icons displayed on primaryContainer background in the launcher

* fix(ui): use onPrimaryContainer instead of primaryText on primaryContainer background

* launcher pills: switch to buttonBg buttonText

---------

Co-authored-by: bbedward <bbedward@gmail.com>
2026-06-17 21:58:11 -04:00
bbedward 9a4cff4e49 settings: fix index conflict on battery tab 2026-06-17 21:30:52 -04:00
Huỳnh Thiện Lộc 480ffa4ac2 feat: add battery settings tab and update battery widget interactions (#2634)
* feat: add battery settings tab and update battery widget interactions

* fix: import Quickshell.Io in BatteryTab.qml to fix Process type compilation error

* feat: move battery tab under media player and add notify when charge limit reached option

* chore: change default notification settings to false

* feat: move battery tab under Power & Security section in settings

* feat: add notification type button selection for battery alerts
2026-06-17 20:29:23 -04:00
dionjoshualobo d5ac0c9aa0 feat(clipboard): add type filters to clipboard history (#2640)
* feat(clipboard): add active filter state

* feat(clipboard): add clipboard filtering logic

* feat(clipboard): wire clipboard filter state to UI

* feat(clipboard): add filter dropdown

* feat(clipboard): move filter dropdown beside search

* refactor(clipboard): update filter defaults

---------

Co-authored-by: purian23 <purian23@gmail.com>
2026-06-17 17:27:45 -04:00
bbedward 29f19b07a9 widgets: fix tooltip position mapping 2026-06-17 12:46:24 -04:00
purian23 39301c534c add: DankColorSwatch component & settings sync 2026-06-17 11:38:25 -04:00
Rocho 58b9e4bda7 fix(dropdown): respect Animation Duration setting for DankDropdown popups (#2661)
DankDropdown popups opened and closed at a fixed speed regardless of the
configured Animation Duration. The Popup inherited Qt Material's default
enter/exit transitions, whose durations are hardcoded and never reference
Theme.shortDuration.

Override enter/exit with theme-driven transitions that keep the Material
grow/fade look (scale + opacity) but read their duration from
Theme.shortDuration, so every DankDropdown instance follows the
animation-speed setting.

Fixes #2659
2026-06-17 09:46:09 -04:00
purian23 820a9ce983 refactor(settings): colors & cleanup 2026-06-17 00:32:58 -04:00
purian23 68410e882d feat(dbar): add workspace & widget color customization options 2026-06-17 00:02:51 -04:00
bbedward f26c0af39a keybinds: add toggle to switch to FloatingWindow and back 2026-06-16 23:03:19 -04:00
Rocho 0ca451483f fix(shell): don't treat DPMS off/on as a screen-reconnect recovery storm (#2654)
A DPMS off/on cycle removes an output from Quickshell.screens and re-adds
it, which DMSShell's onScreensChanged cannot distinguish from a hotplug. It
fired triggerSurfaceRecovery() on every such event; on hardware where
recreating layer-shell surfaces re-wakes the just-powered-down output, this
drives an endless recovery storm that visibly power-cycles the monitor.

Route the screen-reconnect path through a 450 ms debounce (collapsing the
output-remove + re-add pair into a single pass) followed by a 4 s cooldown,
so repeated flaps trigger at most one recovery per window. Recovery still
runs once per resume, so the partial-DPMS-resume recovery added for #2579 is
preserved. The session-resume path runs its own recovery directly and now
clears any queued screen-reconnect recovery to avoid a redundant follow-up.

Fixes #2642
2026-06-16 22:58:21 -04:00
purian23 2849dd0ba2 feat(distros): Add Ubuntu 26.10 Stingray Support 2026-06-16 22:50:58 -04:00
bbedward df41ae4acb running apps: fix blurred tooltips 2026-06-16 18:26:29 -04:00
lingdianshiren 2692777707 fix(weather): robust location resolution with parallel fetch and multi-tier fallback (#2638)
Decouple weather data fetching from reverse geocoding so that
weather loads as soon as coordinates are available, even when
Nominatim is unreachable (e.g. mainland China).

- Fetch Open-Meteo weather immediately once lat/lon are known.
- Resolve city name in parallel via Nominatim -> Photon -> BigDataCloud.
- If all reverse geocoding fails, keep displaying weather with a
  placeholder city name.
- Skip reverse geocoding entirely when the user has configured a
  city name.
- Fall back to ip-api.com when GeoClue2 is unavailable or returns
  zero coordinates.
- Add request-generation tracking to discard stale geocoding
  responses after location changes.
- Hold explicit WeatherService refs in bar widget and dashboard tab.

Co-authored-by: lingdiansr <2077258365@qq.com>
2026-06-16 14:42:01 -04:00
Rocho ca1a45ccf8 fix(lock): dismiss fade-to-lock overlay when using a custom lock command (#2653)
When a custom lock command is configured, Lock.lock() runs the command and
returns early without engaging WlSessionLock, so IdleService.isShellLocked
never transitions true->false. That transition is the only trigger that
dismisses a completed FadeToLockWindow, so the fully-faded black overlay stays
on screen and the desktop is unusable after re-login (regression from b8f4c35,
which added the _completed guard and tied dismissal solely to isShellLocked).

Add a dedicated dismissFadeToLock signal that the custom-lock branch emits
after launching the external locker, mirroring the existing fade signal wiring,
so the overlay is handed off and torn down. The built-in WlSessionLock path is
unchanged and still dismisses on unlock.

Fixes #2595
2026-06-16 13:45:28 -04:00
jbwfu 2f39f248fc fix(network): keep Wi-Fi when password prompt is canceled (#2651) 2026-06-16 12:52:25 -04:00
Rocho 90f8ce5035 feat(sounds): make muting sounds during media playback configurable (#2652)
Commit e3dbaed started skipping all system sounds (notifications, volume,
power, login) whenever an MPRIS player is playing, with no way to opt out.
Users who rely on notification sounds while listening to music lost them
entirely.

Add a 'Mute During Playback' toggle (SettingsData.muteSoundsWhenMediaPlaying,
default true) so the current behaviour is preserved, but users can disable
it to restore audible sounds while media is playing. The media check is
wrapped in shouldMuteForMedia(), which gates on the new setting before
querying the active player.

Closes #2616
2026-06-16 12:49:51 -04:00
Adwait Adhikari cb29125580 add lexical-binding (#2649) 2026-06-16 09:19:38 -04:00
Rocho 988b54515e feat(tailscale): add connect/disconnect, exit-node and LAN-access controls (#2644)
* feat(tailscale): add connect/disconnect/exit-node/LAN-access backend

The Tailscale backend previously exposed only read-only status
(tailscale.getStatus, tailscale.refresh). This adds write actions through the
existing tailscale.com/client/local integration:

- tailscale.connect / tailscale.disconnect (EditPrefs WantRunning)
- tailscale.setExitNode (EditPrefs ExitNodeID; empty id clears it and any
  legacy ExitNodeIP, mirroring `tailscale set --exit-node`)
- tailscale.setAllowLanAccess (EditPrefs ExitNodeAllowLANAccess)

The manager's client interface gains GetPrefs/EditPrefs; fetchState merges
ExitNodeAllowLANAccess from prefs, and Peer exposes ExitNodeOption so the UI
can list exit-node-capable peers.

* feat(tailscale): expose the new actions in TailscaleService

Adds connectTailscale/disconnectTailscale, setExitNode/clearExitNode and
setAllowLanAccess wrappers, plus derived exitNodeOptions/currentExitNode and the
exitNodeAllowLanAccess state. Write-action errors surface via ToastService.

* feat(tailscale): add connection, exit-node and LAN-access controls to the widget

The control-center widget toggle was a no-op. It now connects/disconnects, and
the detail panel gains a connection status row with a connect/disconnect button,
an exit-node picker and a LAN-access toggle.
2026-06-16 09:08:22 -04:00
Rocho 2fd9de5062 fix(keybinds): record numpad keys as KP_* keysyms (#2645)
* fix(keybinds): record numpad keys as KP_* keysyms

The shortcut recorder passed only the Qt key code to xkbKeyFromQtKey and
dropped Qt.KeypadModifier. Since Qt reuses the same Qt::Key_* values for the
numpad and the main row / nav cluster, numpad presses collapsed onto their
twins: numpad-7 became "7" (NumLock on) or "Home" (NumLock off) instead of
"KP_7"/"KP_Home", numpad-+ became "Equal", numpad-* became "8", numpad Enter
became "Return". numpad-5 with NumLock off (Qt.Key_Clear) was missing from the
map entirely, so the capture was silently dropped.

niri and the other providers bind against the xkb KP_* keysym names, so these
tokens never matched the physical key.

Pass the keypad flag through to xkbKeyFromQtKey and map keypad presses to the
KP_* keysyms: KP_0..KP_9 for the NumLock-on digit codes, the navigation names
(KP_Home, KP_End, KP_Up, ...) for the NumLock-off codes, plus the operators
and KP_Enter. Main-row keys are unaffected because they never carry the keypad
modifier.

* fix(keybinds): ignore lock keys while capturing a shortcut

NumLock/CapsLock/ScrollLock are toggles, not useful bind targets. Pressing
NumLock to switch the numpad between its digit and navigation keysyms
(KP_7 vs KP_Home) was captured as the bind itself (e.g. "Super+Num_Lock").
Skip them in the recorder like the other pure modifier keys already are.
2026-06-16 09:07:48 -04:00
Rocho fd5aabcb17 fix(keybinds): parse niri configs with leading-underscore identifiers (#2646)
DMS reads the niri config with kdl-go, which rejects '_' as the first
character of a bare identifier ("unexpected character _") even though niri's
own parser and the KDL spec accept it. The common trigger is the
`_JAVA_AWT_WM_NONREPARENTING "1"` environment node (the standard Java /
tiling-WM fix). When the parse aborts, `dms keybinds show` returns nothing and
the Keyboard Shortcuts UI shows no binds at all.

Extend the existing preprocessor approach (the brace fix from #2230) with
quoteLeadingUnderscoreIdents, which double-quotes bare identifiers that begin
with '_' before the text reaches kdl-go. The scan is string/comment aware and
only touches a leading '_' at a token boundary, so mid-identifier underscores
(XDG_CURRENT_DESKTOP) and underscores inside strings/comments are left alone.
Token boundaries include the ends of block comments and KDL slashdash (/-), so
a node abutting a comment with no whitespace is handled too. This is safe
because the niri parser only dispatches on fixed node/section names that never
start with '_', so re-quoting such a name cannot change what DMS reads.

Refs #2230
2026-06-16 09:06:55 -04:00
jbwfu 85b63219b9 feat(network): add saved WiFi state to settings (#2648) 2026-06-16 09:06:29 -04:00
bbedward ddf943846f i18n: add Vietnamese 2026-06-15 23:47:12 -04:00
purian23 e7221ec623 fix(powermodal): use overlay layer in standalone mode 2026-06-15 21:41:00 -04:00
bbedward 78daaf0cb4 calendar: remove launch button from settings 2026-06-15 19:02:22 -04:00
jbwfu a6ab3bab4c fix(settings): dedupe search index tab entries (#2643) 2026-06-15 16:50:41 -04:00
bbedward 53cea7023f calendar: rename dcal binary 2026-06-15 15:26:06 -04:00
jbwfu a098088f03 refactor(settings): split network settings into tabs (#2633) 2026-06-15 15:21:02 -04:00
bbedward 59998e9fd2 calendar(dank): Add support for DankCalendar backend
- Add keyboard navigation to overview
- Add edit events to overview
- Add create events to overview
- Add setting for auto/khal/dankcalendar backend selection
2026-06-15 14:02:35 -04:00
purian23 1df7e478df fix(FileBrowser): Improve save-to-file handling w/safety override diags
Fixes #2641
2026-06-15 01:11:32 -04:00
Artrix 1fc4890857 tray: add automatic overflow popup (#2629) 2026-06-15 00:10:02 -04:00
purian23 f5d52f1506 update(ipc): docs & dms ipc list 2026-06-14 23:35:22 -04:00
purian23 2026ba5bd2 fix(Notepad): clean up edge cases & updated popout handling 2026-06-14 22:15:34 -04:00
purian23 db56c8d74d feat(Notepad): Complete refactor - New popout mode & settings
- Add a full popout Notepad experience w/new layout settings
- New ability to choose the left or right side of the screen
- Add more safegaurds to preserve user data throughout
- New banner to show file reload/conflict handling
- New extensionless file support
- Polish settings with gap controls, compact buttons, and shortcuts help
2026-06-14 20:20:36 -04:00
Huỳnh Thiện Lộc 9d1a81c93c feat(media-control): support scroll and right-click on audio output devices in media popout (#2615)
* feat(media-control): support scroll and right-click on audio output devices in media popout

* feat(media-control): make device list volume scrolling optional
2026-06-13 17:51:03 -04:00
bbedward 3701b3d7a3 wallpaper: re-introduce updatesEnabled 2026-06-12 20:00:53 -04:00
purian23 bae98daa5c fix(wallpaper): simplify wallpaper rendering logic & reliability
- Keep wallpaper surfaces persistent and remove `updatesEnabled` throttling that could leave wallpapers grey or frozen after DPMS, suspend, fullscreen, or output changes

Fixes #2612
Fixes #2299
Fixes #2272
Fixes #2028
2026-06-12 17:30:54 -04:00
jbwfu b34a04f723 fix(clipboard): hide pin action while keeping saved indicator (#2626) 2026-06-12 15:39:23 -04:00
purian23 1c0245f2db fix(translations): add newline at end of JSON file and output file 2026-06-12 15:06:36 -04:00
purian23 7777e87dc8 refactor(settings): reorg to break out sections and verbiage 2026-06-12 14:57:25 -04:00
jbwfu 820fa07846 feat(settings): add clipboard entry action visibility controls (#2621)
* feat(settings): add clipboard entry action visibility controls

* fix(clipboard): show pinned indicator for saved entries when pin action is hidden
2026-06-12 14:08:05 -04:00
purian23 66794582c9 fix(fullscreen): retain user dbar standalone configs while in framemode fullscreen 2026-06-12 12:39:38 -04:00
jbwfu 73eb471ae3 fix(clipboard): keep first item selected when navigating upward (#2622) 2026-06-12 11:35:07 -04:00
jbwfu 0f2f4b96c4 Fix/clipboard confirmation keyboard safety (#2623)
* fix(clipboard): improve confirmation dialog keyboard focus

* fix(clipboard): require confirmation for clear-all shortcut
2026-06-12 11:34:16 -04:00
purian23 d53809cf2b refactor(framemode): unify connected surface chrome via SDF pipeline
- Shadow system rewrite with SDF quads
- Replace ConnectedShape/layer FBOs w/frame & chrome SDF shaders
- Improve frame blur performance
- Plugin performance gate
2026-06-12 11:03:39 -04:00
Klesh Wong 08fd6e26d8 feat(notifications): user-configurable font size for notification summary and body (#2461)
* feat(notifications): add user-configurable font size for summary and body in notification popups

* feat: add Unset for falling back to previous default values

* fix: prek hook errors

---------

Co-authored-by: Klesh Wong <kleshwong@gmail.com>
2026-06-11 15:40:33 -04:00
Youseffo13 29e8470f2e fix(settings): fix text truncation in some section of settings and update icons (#2618)
* fixed spacing issues

* added one missing icon and replaced two
2026-06-11 15:35:51 -04:00
Bogdan Velicu 573785d4ce feat(notifications): add opt-in timeout progress bar on popups (#2587)
Adds a thin bar pinned to the bottom of the notification card that drains
full->empty over the auto-dismiss timer, as a visual countdown to
dismissal. Opt-in via notificationShowTimeoutBar (default off), with a
toggle in Settings > Notifications. Shown for any timed notification
(timer.interval > 0, including timed criticals); inset by the corner
radius, and frozen while hovered or during the exit animation. Plain
Rectangle - no offscreen textures or shader passes. A Connections on the
timer resets the bar on every (re)start, including the in-place restart
on a deduped notification.

Co-authored-by: bogdan-velicu <hydrotech074@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 15:22:22 -04:00
jbwfu 5483303714 Fix/clipboard pinned recents dedupe (#2605)
* fix(clipboard): unpin pinned duplicates from history entries

* fix(clipboard): dedupe recents when using pinned entries
2026-06-11 15:05:28 -04:00
David Mireles 5a5cc4f4e9 feat(plugins): expose scan/rescan/reload IPC handlers for runtime plugin discovery (#2611)
* feat(plugins): expose IPC handlers for runtime plugin discovery

Follow-up to #1659. That issue landed hot-reload for settings.json via
FileView.watchChanges + a 1ms Timer to skirt the JSON parse race. It does
not cover plugin discovery in runtime: adding a new plugin directory to
~/.config/DankMaterialShell/plugins/ while the shell is running is not
consistently picked up by the existing FolderListModel watcher in
PluginService.qml, and there is no IPC handle for forcing a rescan from
outside the shell.

Adds an IpcHandler on PluginService with five small functions:

- scan(): wraps existing scanPlugins(), returns count snapshot
- rescan(pluginId): wraps existing forceRescanPlugin(id), validates id
- reload(pluginId): wraps existing reloadPlugin(id), validates id
- list(): newline-joined id\tloaded\ttype\tname for every known plugin
- status(pluginId): loaded\ttype\terror for one plugin

Scope intentionally small: no file-watcher changes, no new daemons, no
schema additions. Target string "plugins" does not collide with any
existing target in DMSShellIPC.qml.

Validation:
- qs ipc --pid <PID> call plugins list returns one row per known plugin
- qs ipc --pid <PID> call plugins scan returns SCAN_TRIGGERED with count
- qs ipc --pid <PID> call plugins rescan <id> returns RESCAN_TRIGGERED
- Empty-arg paths return ERROR strings instead of throwing
- git merge-tree against origin/master is clean

* hardening(plugins): fix 7 review findings in scan-ipc IPC handlers

Follow-up to commit 43603f56 which ported PR #2601 (AvengeMedia scan-ipc)
to the fork. The original port was functionally correct but had seven
review issues that would block upstream adoption. This patch addresses
each one with a minimal, focused change.

* B1 IPC target collision: renamed `target: "plugins"` to
  `target: "plugin-scan"`. The original name collided with the
  existing IpcHandler in DMSShellIPC.qml:1180 which already registers
  enable/disable/toggle/list/status under "plugins". The split keeps
  both APIs discoverable without one shadowing the other.

* H1 Fire-and-forget scan: documented that scan() returns the
  pre-debounce count and that callers must poll list/status (or wait
  ~200ms) to observe the post-debounce state. A proper requestId +
  await mechanism was considered and rejected for scope reasons.

* H2 TOCTOU in rescan(): the handler now reads availablePlugins[id]
  inside forceRescanPlugin via the id string only — no captured
  object reference. A parallel resyncDebounce tick can otherwise
  mutate the entry between the read and the use.

* M1 list() cap: added a 256-entry cap and a leading header line
  (`# count=N returned=M`) so callers can detect truncation. A
  hostile / buggy plugin mass-creating entries could otherwise
  allocate 80 KB+ per IPC call.

* M2 status() prefix: "unknown\t\t" became
  `ERROR: unknown pluginId '...'` to match the rest of the
  handlers' prefix convention. Empty trailing field means no error.

* M3 id sanitization: every handler that takes pluginId now
  validates against `/^[a-zA-Z0-9_\-:]{1,64}$` before use. This
  rejects shell-injection payloads ("foo\tmalicious") and prototype
  pollution attempts ("__proto__", "constructor"). The list() and
  status() handlers also sanitize \t/\n in name and error fields
  so callers can rely on the TSV structure.

Verification: brace count balanced (252/252). Manual read of all
five handlers confirms no logic regression. QML runtime tests are
not part of the DMS test suite, so end-to-end validation requires
rebuilding the shell — deferred to the user.

Not pushed. Stage-local-first rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(plugins): strip inline comments per review feedback

Purian23 in PR #2611 review: 'let's address the amount of line
comments in the code, there's not a need for all of them to exist.'

Removed 48 comment lines. The substantive justification (why the
regex, why fire-and-forget, why re-read inside forceRescanPlugin,
why the 256 cap, why the target rename) now lives in the PR body
under 'Review-driven fixes in this iteration' and 'What changed'
where the reviewer already reads it.

No code logic changed. Brace count 252/252. Diff is -48/+0 on
quickshell/Services/PluginService.qml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------
2026-06-11 14:44:41 -04:00
bbedward cd672c341f settings: add DankSpinner, re-org some settings 2026-06-10 18:53:43 -04:00
bbedward 12438d63c2 mango: remove legacy dwl service 2026-06-10 17:01:03 -04:00
Ralph Zhou 35255e4053 fix(lock): bypass IME for password input (#2609) 2026-06-10 16:29:05 -04:00
goatnath 8856d45887 add local to-do planner / tasks to calendar overvie… (#2583)
* feat(quickshell): add local to-do planner / tasks to calendar overview card

* feat(quickshell): add auto-focus and task reordering support in calendar planner

* feat(quickshell): implement smooth drag-and-drop task reordering and inline editing

* fix(quickshell): resolve overlap and jitter in task drag-and-drop

* fix(quickshell): fix boundary swaps and prevent task list scrambling on reload

* fix(quickshell): resolve race, fix qml error, simplify dragging, and remove python dependency

* fix(quickshell): use Log service instead of console.warn in CalendarService

* style: format QML files w/qmlformat-qt6

---------
2026-06-09 00:43:41 -04:00
jbwfu 38af56c6fd fix(clipboard): exit saved filter when pinned entries are empty (#2604) 2026-06-08 23:54:06 -04:00
jbwfu 9111e4809d fix(powermenu): close control center on lock and power actions (#2598) 2026-06-08 23:53:43 -04:00
purian23 d08c7c5e55 refactor(frame): improve connected mode surface recovery
- share modal and launcher ownership handling
- recover missing background and blur layers
2026-06-07 17:47:24 -04:00
purian23 69f3dee25a feat(settings): add compositor section & restructured settings
- add dedicated Compositor pages for comp specifc features
- add Dank Bar Appearance subsection
- improve lazy loading, caching, search routing, & IPC navigation
- standardized responsive Setting categories from global animations
2026-06-07 03:52:00 -04:00
purian23 8155970ba2 fix(fonts): auto-rebuild font cache when configured fonts are missing
- Add Fonts category to dms doctor for manual diagnostics
- Fix a default font setting warning
2026-06-06 19:24:52 -04:00
pathmann d356957dad fix: ignore keyboard shortcuts of disabled powermenu actions (#2580)
* fix: ignore keyboard shortcuts of disabled powermenu actions

* fix typo when checking for lock shortcut

* ignore shortcuts for hidden powermenu actions in grid navigation

* ignore keyboard shortcuts of disabled actions in lock power menu

* ignore keyboard shortcuts of disabled actions in lock power menu (list navigation)
2026-06-06 18:28:38 -04:00
purian23 e7ccb702a3 refactor: update KeybindsModal dynamic sizing 2026-06-05 23:17:14 -04:00
Connor Welsh bf3ce6deb2 fix(osd): size from PanelWindow.screen (#2582) 2026-06-05 23:14:51 -04:00
purian23 f5295fb35d fix(greeter): remove auto-login state resolution from first install configuration
- Update auto-login command to:
`dms greeter sync --autologin`
2026-06-05 23:05:56 -04:00
purian23 6c5836722a fix(authModals): enable overlay layer for for auth popups 2026-06-05 21:27:37 -04:00
Youseffo13 5716249bd9 (Control Center): revamp of 25% pill option (#2568)
* revamp of control center

* update comment of SmallCompoundButton.qml
2026-06-05 19:46:01 -04:00
purian23 4d0aab773b fix(wallpaper): external management toggle & partial monitor DPMS recovery
Fixes #2579, #2581
2026-06-05 19:36:23 -04:00
purian23 e50ac208e3 feat(mangowm): add live config reloads & misc QOL updates
- Hide workspace tags during Mango overview
- Add HJKL focus/move defaults
- Add Mango natural touchpad scrolling &  cursor configs
- Fix Mango startup
2026-06-05 10:53:26 -04:00
bbedward bcb5617194 plugins: add support for composite plugins
- single plugin can register multiple types - e.g. daemon, bar widget,
  desktop widget
2026-06-05 10:33:34 -04:00
bbedward d3c23ba737 settings: add missing tabs to index and tweak search scoring 2026-06-05 09:49:49 -04:00
374 changed files with 62561 additions and 22322 deletions
@@ -235,7 +235,7 @@ Conditionally show/hide the bar pill:
```qml ```qml
PluginComponent { PluginComponent {
visibilityCommand: "pgrep -x myapp" visibilityCommand: "pgrep -x myapp"
visibilityInterval: 5000 // check every 5 seconds visibilityInterval: 5 // seconds between checks; polling pauses while the bar is hidden
} }
``` ```
+8
View File
@@ -115,3 +115,11 @@ core.*
.direnv/ .direnv/
quickshell/dms-plugins quickshell/dms-plugins
__pycache__ __pycache__
.vscode/
# Void (xbps) build artifacts
*.xbps
distro/void/temp/
distro/void/hostdir/
distro/void/masterdir*/
+8
View File
@@ -20,6 +20,14 @@ repos:
language: system language: system
files: ^core/.*\.(go|mod|sum)$ files: ^core/.*\.(go|mod|sum)$
pass_filenames: false pass_filenames: false
- repo: local
hooks:
- id: settings-search-index
name: settings search index is up to date
entry: bash -c 'python3 quickshell/translations/extract_settings_index.py >/dev/null || exit 1; if ! git diff --exit-code -- quickshell/translations/settings_search_index.json; then echo "settings_search_index.json is out of date; run quickshell/translations/extract_settings_index.py and stage the result" >&2; exit 1; fi'
language: system
files: ^quickshell/(Modules/Settings/.*\.qml|Modals/Settings/SettingsSidebar\.qml|translations/extract_settings_index\.py)$
pass_filenames: false
- repo: local - repo: local
hooks: hooks:
- id: no-console-in-qml - id: no-console-in-qml
+65 -62
View File
@@ -1,82 +1,85 @@
with-expecter: true dir: internal/mocks/{{.InterfaceDirRelative}}
dir: "internal/mocks/{{.InterfaceDirRelative}}" structname: Mock{{.InterfaceName}}
mockname: "Mock{{.InterfaceName}}" pkgname: '{{.SrcPackageName}}'
outpkg: "{{.PackageName}}" filename: 'mock_{{.InterfaceName}}.go'
template: testify
template-data:
unroll-variadic: true
packages: packages:
github.com/Wifx/gonetworkmanager/v2:
interfaces:
NetworkManager:
Device:
DeviceWireless:
AccessPoint:
Connection:
Settings:
ActiveConnection:
IP4Config:
net:
interfaces:
Conn:
github.com/AvengeMedia/danklinux/internal/plugins:
interfaces:
GitClient:
github.com/godbus/dbus/v5:
interfaces:
BusObject:
github.com/AvengeMedia/danklinux/internal/server/brightness:
config:
dir: "internal/mocks/brightness"
outpkg: mocks_brightness
interfaces:
DBusConn:
github.com/AvengeMedia/DankMaterialShell/core/internal/geolocation: github.com/AvengeMedia/DankMaterialShell/core/internal/geolocation:
config: config:
dir: "internal/mocks/geolocation" dir: internal/mocks/geolocation
outpkg: mocks_geolocation pkgname: mocks_geolocation
interfaces: interfaces:
Client: Client: {}
github.com/AvengeMedia/DankMaterialShell/core/internal/server/network:
config:
dir: "internal/mocks/network"
outpkg: mocks_network
interfaces:
Backend:
github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups: github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups:
config: config:
dir: "internal/mocks/cups" dir: internal/mocks/cups
outpkg: mocks_cups pkgname: mocks_cups
interfaces: interfaces:
CUPSClientInterface: CUPSClientInterface: {}
PkHelper: PkHelper:
config: config:
dir: "internal/mocks/cups_pkhelper" dir: internal/mocks/cups_pkhelper
outpkg: mocks_cups_pkhelper pkgname: mocks_cups_pkhelper
github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev: github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev:
config: config:
dir: "internal/mocks/evdev" dir: internal/mocks/evdev
outpkg: mocks_evdev pkgname: mocks_evdev
interfaces: interfaces:
EvdevDevice: EvdevDevice: {}
github.com/AvengeMedia/DankMaterialShell/core/internal/version: github.com/AvengeMedia/DankMaterialShell/core/internal/server/network:
config: config:
dir: "internal/mocks/version" dir: internal/mocks/network
outpkg: mocks_version pkgname: mocks_network
interfaces: interfaces:
VersionFetcher: Backend: {}
github.com/AvengeMedia/DankMaterialShell/core/internal/server/wlcontext: github.com/AvengeMedia/DankMaterialShell/core/internal/server/wlcontext:
config: config:
dir: "internal/mocks/wlcontext" dir: internal/mocks/wlcontext
outpkg: mocks_wlcontext pkgname: mocks_wlcontext
interfaces: interfaces:
WaylandContext: WaylandContext: {}
github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client:
config:
dir: "internal/mocks/wlclient"
outpkg: mocks_wlclient
interfaces:
WaylandDisplay:
github.com/AvengeMedia/DankMaterialShell/core/internal/utils: github.com/AvengeMedia/DankMaterialShell/core/internal/utils:
config: config:
dir: "internal/mocks/utils" dir: internal/mocks/utils
outpkg: mocks_utils pkgname: mocks_utils
interfaces: interfaces:
AppChecker: AppChecker: {}
github.com/AvengeMedia/DankMaterialShell/core/internal/version:
config:
dir: internal/mocks/version
pkgname: mocks_version
interfaces:
VersionFetcher: {}
github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client:
config:
dir: internal/mocks/wlclient
pkgname: mocks_wlclient
interfaces:
WaylandDisplay: {}
github.com/AvengeMedia/DankMaterialShell/core/internal/plugins:
interfaces:
GitClient: {}
github.com/AvengeMedia/DankMaterialShell/core/internal/server/brightness:
config:
dir: internal/mocks/brightness
pkgname: mocks_brightness
interfaces:
DBusConn: {}
github.com/Wifx/gonetworkmanager/v2:
interfaces:
AccessPoint: {}
ActiveConnection: {}
Connection: {}
Device: {}
DeviceWireless: {}
IP4Config: {}
NetworkManager: {}
Settings: {}
github.com/godbus/dbus/v5:
interfaces:
BusObject: {}
net:
interfaces:
Conn: {}
+9 -1
View File
@@ -19,7 +19,12 @@ var (
var colorCmd = &cobra.Command{ var colorCmd = &cobra.Command{
Use: "color", Use: "color",
Short: "Color utilities", Short: "Color utilities",
Long: "Color utilities including picking colors from the screen", Long: `Color utilities including picking colors from the screen.
This is the screen eyedropper CLI. To open the in-shell color modal, use:
dms ipc call color-picker toggle
See: https://danklinux.com/docs/dankmaterialshell/keybinds-ipc`,
} }
var colorPickCmd = &cobra.Command{ var colorPickCmd = &cobra.Command{
@@ -29,6 +34,9 @@ var colorPickCmd = &cobra.Command{
Click on any pixel to capture its color, or press Escape to cancel. Click on any pixel to capture its color, or press Escape to cancel.
This is the screen eyedropper CLI. To open the in-shell color modal, use:
dms ipc call color-picker toggle
Output format flags (mutually exclusive, default: --hex): Output format flags (mutually exclusive, default: --hex):
--hex - Hexadecimal (#RRGGBB) --hex - Hexadecimal (#RRGGBB)
--rgb - RGB values (R G B) --rgb - RGB values (R G B)
+16 -3
View File
@@ -77,10 +77,15 @@ var killCmd = &cobra.Command{
} }
var ipcCmd = &cobra.Command{ var ipcCmd = &cobra.Command{
Use: "ipc [target] [function] [args...]", Use: "ipc",
Short: "Send IPC commands to running DMS shell", Short: "Send IPC commands to running DMS shell",
Long: `Send IPC commands to the running DMS shell.
dms ipc call <target> <function> [args...] invoke a command
dms ipc list list all targets and functions
Full reference: https://danklinux.com/docs/dankmaterialshell/keybinds-ipc`,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
_ = findConfig(cmd, args)
return getShellIPCCompletions(args, toComplete), cobra.ShellCompDirectiveNoFileComp return getShellIPCCompletions(args, toComplete), cobra.ShellCompDirectiveNoFileComp
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@@ -88,9 +93,17 @@ var ipcCmd = &cobra.Command{
}, },
} }
var ipcListCmd = &cobra.Command{
Use: "list",
Short: "List all IPC targets and functions",
Run: func(cmd *cobra.Command, args []string) {
printIPCHelp()
},
}
func init() { func init() {
ipcCmd.AddCommand(ipcListCmd)
ipcCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { ipcCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
_ = findConfig(cmd, args)
printIPCHelp() printIPCHelp()
}) })
} }
+1 -1
View File
@@ -72,7 +72,7 @@ func runResolveInclude(cmd *cobra.Command, args []string) {
result, err = checkHyprlandInclude(filename) result, err = checkHyprlandInclude(filename)
case "niri": case "niri":
result, err = checkNiriInclude(filename) result, err = checkNiriInclude(filename)
case "mangowc", "dwl", "mango": case "mangowc", "mango":
result, err = checkMangoWCInclude(filename) result, err = checkMangoWCInclude(filename)
default: default:
log.Fatalf("Unknown compositor: %s", compositor) log.Fatalf("Unknown compositor: %s", compositor)
+101
View File
@@ -125,6 +125,7 @@ const (
catConfigFiles catConfigFiles
catServices catServices
catEnvironment catEnvironment
catFonts
) )
func (c category) String() string { func (c category) String() string {
@@ -147,6 +148,8 @@ func (c category) String() string {
return "Services" return "Services"
case catEnvironment: case catEnvironment:
return "Environment" return "Environment"
case catFonts:
return "Fonts"
default: default:
return "Unknown" return "Unknown"
} }
@@ -213,6 +216,7 @@ func runDoctor(cmd *cobra.Command, args []string) {
checkConfigurationFiles(), checkConfigurationFiles(),
checkSystemdServices(), checkSystemdServices(),
checkEnvironmentVars(), checkEnvironmentVars(),
checkFonts(),
) )
switch { switch {
@@ -1135,3 +1139,100 @@ func formatResultsPlain(results []checkResult) string {
return sb.String() return sb.String()
} }
func checkFonts() []checkResult {
var results []checkResult
url := doctorDocsURL + "#fonts"
configDir, err := os.UserConfigDir()
if err != nil {
return nil
}
settingsPath := filepath.Join(configDir, "DankMaterialShell", "settings.json")
fontFamily := "Inter Variable"
monoFontFamily := "Fira Code"
if data, err := os.ReadFile(settingsPath); err == nil {
var settings struct {
FontFamily string `json:"fontFamily"`
MonoFontFamily string `json:"monoFontFamily"`
}
if err := json.Unmarshal(data, &settings); err == nil {
if settings.FontFamily != "" {
fontFamily = settings.FontFamily
}
if settings.MonoFontFamily != "" {
monoFontFamily = settings.MonoFontFamily
}
}
}
if !utils.CommandExists("fc-list") {
results = append(results, checkResult{catFonts, "Fontconfig Tools", statusWarn, "fc-list not installed", "Cannot verify if fonts are cached.", url})
return results
}
// Retrieve font list
output, err := exec.Command("fc-list", ":", "family").Output()
if err != nil {
results = append(results, checkResult{catFonts, "Fontconfig Cache", statusError, "Failed to query font list", "Fontconfig cache query failed. Try running 'fc-cache -fv'.", url})
return results
}
outStr := string(output)
if len(strings.TrimSpace(outStr)) == 0 {
results = append(results, checkResult{catFonts, "Fontconfig Cache", statusError, "Cache is empty", "No fonts found in fontconfig cache. Try running 'fc-cache -fv'.", url})
return results
}
lowerFonts := strings.ToLower(outStr)
// Helper to check if a font exists
hasFont := func(name string) bool {
target := strings.ToLower(strings.TrimSpace(name))
if target == "" {
return false
}
for _, line := range strings.Split(lowerFonts, "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
// Each line can have comma-separated families
families := strings.Split(line, ",")
for _, fam := range families {
if strings.TrimSpace(fam) == target {
return true
}
}
}
return false
}
// Normal Font Check
if hasFont(fontFamily) {
results = append(results, checkResult{catFonts, "Normal Font", statusOK, fontFamily, "Available", url})
} else {
results = append(results, checkResult{
catFonts, "Normal Font", statusWarn,
fmt.Sprintf("'%s' not found", fontFamily),
"Font is not registered. Try running 'fc-cache -fv' or install the font.",
url,
})
}
// Monospace Font Check
if hasFont(monoFontFamily) {
results = append(results, checkResult{catFonts, "Monospace Font", statusOK, monoFontFamily, "Available", url})
} else {
results = append(results, checkResult{
catFonts, "Monospace Font", statusWarn,
fmt.Sprintf("'%s' not found", monoFontFamily),
"Font is not registered. Try running 'fc-cache -fv' or install the font.",
url,
})
}
return results
}
+89 -7
View File
@@ -75,7 +75,7 @@ var greeterSyncCmd = &cobra.Command{
auth, _ := cmd.Flags().GetBool("auth") auth, _ := cmd.Flags().GetBool("auth")
local, _ := cmd.Flags().GetBool("local") local, _ := cmd.Flags().GetBool("local")
profile, _ := cmd.Flags().GetBool("profile") profile, _ := cmd.Flags().GetBool("profile")
autologinOnly, _ := cmd.Flags().GetBool("autologin-only") autologinOnly, _ := cmd.Flags().GetBool("autologin")
term, _ := cmd.Flags().GetBool("terminal") term, _ := cmd.Flags().GetBool("terminal")
if term { if term {
if err := syncInTerminal(yes, auth, local, profile, autologinOnly); err != nil { if err := syncInTerminal(yes, auth, local, profile, autologinOnly); err != nil {
@@ -95,13 +95,45 @@ var greeterSyncCmd = &cobra.Command{
}, },
} }
var greeterLaunchSessionCmd = &cobra.Command{
Use: "launch-session",
Short: "Launch a remembered greeter session",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
sessionID, _ := cmd.Flags().GetString("session-id")
fromMemory, _ := cmd.Flags().GetBool("from-memory")
cacheDir, _ := cmd.Flags().GetString("cache-dir")
if fromMemory {
homeDir, err := os.UserHomeDir()
if err != nil {
log.Fatalf("failed to get user home directory: %v", err)
}
if err := greeter.LaunchSessionFromMemory(cacheDir, homeDir); err != nil {
log.Fatalf("failed to launch remembered greeter session: %v", err)
}
return
}
if sessionID == "" {
log.Fatal("missing --session-id or --from-memory")
}
if err := greeter.LaunchSessionByID(sessionID); err != nil {
log.Fatalf("failed to launch greeter session %q: %v", sessionID, err)
}
},
}
func init() { func init() {
greeterSyncCmd.Flags().BoolP("yes", "y", false, "Non-interactive mode: skip prompts, use defaults (for UI)") greeterSyncCmd.Flags().BoolP("yes", "y", false, "Non-interactive mode: skip prompts, use defaults (for UI)")
greeterSyncCmd.Flags().BoolP("terminal", "t", false, "Run sync in a new terminal (for entering sudo password); terminal auto-closes when done") greeterSyncCmd.Flags().BoolP("terminal", "t", false, "Run sync in a new terminal (for entering sudo password); terminal auto-closes when done")
greeterSyncCmd.Flags().BoolP("auth", "a", false, "Configure PAM for fingerprint and U2F (adds both if modules exist); overrides UI toggles") greeterSyncCmd.Flags().BoolP("auth", "a", false, "Configure PAM for fingerprint and U2F (adds both if modules exist); overrides UI toggles")
greeterSyncCmd.Flags().BoolP("local", "l", false, "Developer mode: force greetd config to use a local DMS checkout path") greeterSyncCmd.Flags().BoolP("local", "l", false, "Developer mode: force greetd config to use a local DMS checkout path")
greeterSyncCmd.Flags().BoolP("profile", "p", false, "Sync only your per-user greeter slot (no sudo; for secondary accounts)") greeterSyncCmd.Flags().BoolP("profile", "p", false, "Sync only your per-user greeter slot (no sudo; for secondary accounts)")
greeterSyncCmd.Flags().Bool("autologin-only", false, "Apply only greeter auto-login on startup settings to greetd (no theme or auth sync)") greeterSyncCmd.Flags().Bool("autologin", false, "Apply only greeter auto-login on startup settings to greetd (no theme or auth sync)")
greeterLaunchSessionCmd.Flags().String("session-id", "", "Desktop session id to launch")
greeterLaunchSessionCmd.Flags().Bool("from-memory", false, "Resolve the session id from greeter memory")
greeterLaunchSessionCmd.Flags().String("cache-dir", greeter.GreeterCacheDir, "Greeter cache directory")
} }
var greeterEnableCmd = &cobra.Command{ var greeterEnableCmd = &cobra.Command{
@@ -299,7 +331,7 @@ func installGreeter(nonInteractive bool) error {
fmt.Println("\n=== Installation Complete ===") fmt.Println("\n=== Installation Complete ===")
fmt.Println("\nTo start the greeter now, run:") fmt.Println("\nTo start the greeter now, run:")
fmt.Println(" sudo systemctl start greetd") fmt.Println(startGreeterHint())
fmt.Println("\nOr reboot to see the greeter at next boot.") fmt.Println("\nOr reboot to see the greeter at next boot.")
return nil return nil
@@ -326,7 +358,13 @@ func uninstallGreeter(nonInteractive bool) error {
} }
fmt.Println("\nDisabling greetd...") fmt.Println("\nDisabling greetd...")
if err := privesc.Run(context.Background(), "", "systemctl", "disable", "greetd"); err != nil { if isRunit() {
if err := disableRunitService("greetd"); err != nil {
fmt.Printf(" ⚠ Could not disable greetd: %v\n", err)
} else {
fmt.Println(" ✓ greetd disabled")
}
} else if err := privesc.Run(context.Background(), "", "systemctl", "disable", "greetd"); err != nil {
fmt.Printf(" ⚠ Could not disable greetd: %v\n", err) fmt.Printf(" ⚠ Could not disable greetd: %v\n", err)
} else { } else {
fmt.Println(" ✓ greetd disabled") fmt.Println(" ✓ greetd disabled")
@@ -449,6 +487,14 @@ func suggestDisplayManagerRestore(nonInteractive bool) {
enableDM := func(dm string) { enableDM := func(dm string) {
fmt.Printf(" Enabling %s...\n", dm) fmt.Printf(" Enabling %s...\n", dm)
if isRunit() {
if err := enableRunitService(dm); err != nil {
fmt.Printf(" ⚠ Failed to enable %s: %v\n", dm, err)
} else {
fmt.Printf(" ✓ %s enabled (linked into %s).\n", dm, runitServiceDir)
}
return
}
if err := privesc.Run(context.Background(), "", "systemctl", "enable", "--force", dm); err != nil { if err := privesc.Run(context.Background(), "", "systemctl", "enable", "--force", dm); err != nil {
fmt.Printf(" ⚠ Failed to enable %s: %v\n", dm, err) fmt.Printf(" ⚠ Failed to enable %s: %v\n", dm, err)
} else { } else {
@@ -495,6 +541,9 @@ func suggestDisplayManagerRestore(nonInteractive bool) {
} }
func isSystemdUnitInstalled(unit string) bool { func isSystemdUnitInstalled(unit string) bool {
if isRunit() {
return runitServiceInstalled(unit)
}
cmd := exec.Command("systemctl", "list-unit-files", unit+".service", "--no-legend", "--no-pager") cmd := exec.Command("systemctl", "list-unit-files", unit+".service", "--no-legend", "--no-pager")
out, err := cmd.Output() out, err := cmd.Output()
return err == nil && strings.Contains(string(out), unit) return err == nil && strings.Contains(string(out), unit)
@@ -544,7 +593,7 @@ func syncInTerminal(nonInteractive bool, forceAuth bool, local bool, profileOnly
syncFlags = append(syncFlags, "--profile") syncFlags = append(syncFlags, "--profile")
} }
if autologinOnly { if autologinOnly {
syncFlags = append(syncFlags, "--autologin-only") syncFlags = append(syncFlags, "--autologin")
} }
shellSyncCmd := "dms greeter sync" shellSyncCmd := "dms greeter sync"
if len(syncFlags) > 0 { if len(syncFlags) > 0 {
@@ -943,6 +992,18 @@ func resolveLocalDMSPath() (string, error) {
} }
func disableDisplayManager(dmName string) (bool, error) { func disableDisplayManager(dmName string) (bool, error) {
if isRunit() {
if !runitServiceEnabled(dmName) {
return false, nil
}
fmt.Printf("\nDisabling %s (runit)...\n", dmName)
if err := disableRunitService(dmName); err != nil {
return false, fmt.Errorf("failed to disable %s: %w", dmName, err)
}
fmt.Printf(" ✓ %s disabled (removed from %s)\n", dmName, runitServiceDir)
return true, nil
}
state, err := getSystemdServiceState(dmName) state, err := getSystemdServiceState(dmName)
if err != nil { if err != nil {
return false, fmt.Errorf("failed to check %s state: %w", dmName, err) return false, fmt.Errorf("failed to check %s state: %w", dmName, err)
@@ -996,6 +1057,21 @@ func disableDisplayManager(dmName string) (bool, error) {
} }
func ensureGreetdEnabled() error { func ensureGreetdEnabled() error {
if isRunit() {
fmt.Println("\nEnabling greetd service (runit)...")
if !runitServiceInstalled("greetd") {
return fmt.Errorf("greetd service not found in %s. Please install greetd first", runitSvDir)
}
// Seat + runtime-dir setup that logind handles automatically on systemd.
ensureRunitSeat("_greeter")
ensureGreetdPamRundir()
if err := enableRunitService("greetd"); err != nil {
return fmt.Errorf("failed to enable greetd: %w", err)
}
fmt.Printf(" ✓ greetd enabled (%s)\n", runitServiceDir)
return nil
}
fmt.Println("\nChecking greetd service status...") fmt.Println("\nChecking greetd service status...")
state, err := getSystemdServiceState("greetd") state, err := getSystemdServiceState("greetd")
@@ -1043,6 +1119,12 @@ func ensureGreetdEnabled() error {
} }
func ensureGraphicalTarget() error { func ensureGraphicalTarget() error {
if isRunit() {
// runit has no targets; a supervised greetd service is the graphical
// login, so there is nothing to set here.
return nil
}
getDefaultCmd := exec.Command("systemctl", "get-default") getDefaultCmd := exec.Command("systemctl", "get-default")
currentTarget, err := getDefaultCmd.Output() currentTarget, err := getDefaultCmd.Output()
if err != nil { if err != nil {
@@ -1176,7 +1258,7 @@ func enableGreeter(nonInteractive bool) error {
fmt.Println("\n=== Enable Complete ===") fmt.Println("\n=== Enable Complete ===")
fmt.Println("\nGreeter configuration verified and system state corrected.") fmt.Println("\nGreeter configuration verified and system state corrected.")
fmt.Println("To start the greeter now, run:") fmt.Println("To start the greeter now, run:")
fmt.Println(" sudo systemctl start greetd") fmt.Println(startGreeterHint())
fmt.Println("\nOr reboot to see the greeter at boot time.") fmt.Println("\nOr reboot to see the greeter at boot time.")
return nil return nil
@@ -1257,7 +1339,7 @@ func enableGreeter(nonInteractive bool) error {
fmt.Println("\n=== Enable Complete ===") fmt.Println("\n=== Enable Complete ===")
fmt.Println("\nTo start the greeter now, run:") fmt.Println("\nTo start the greeter now, run:")
fmt.Println(" sudo systemctl start greetd") fmt.Println(startGreeterHint())
fmt.Println("\nOr reboot to see the greeter at boot time.") fmt.Println("\nOr reboot to see the greeter at boot time.")
return nil return nil
+2 -2
View File
@@ -39,7 +39,7 @@ Modes:
full - Capture the focused output full - Capture the focused output
all - Capture all outputs combined all - Capture all outputs combined
output - Capture a specific output by name output - Capture a specific output by name
window - Capture the focused window (Hyprland/DWL) window - Capture the focused window (Hyprland/Mango)
last - Capture the last selected region last - Capture the last selected region
Output format (--format): Output format (--format):
@@ -97,7 +97,7 @@ If no previous region exists, falls back to interactive selection.`,
var ssWindowCmd = &cobra.Command{ var ssWindowCmd = &cobra.Command{
Use: "window", Use: "window",
Short: "Capture the focused window", Short: "Capture the focused window",
Long: `Capture the currently focused window. Supported on Hyprland and DWL.`, Long: `Capture the currently focused window. Supported on Hyprland and Mango.`,
Run: runScreenshotWindow, Run: runScreenshotWindow,
} }
+8 -1
View File
@@ -294,7 +294,14 @@ func runSetup() error {
wm, wmSelected := promptCompositor() wm, wmSelected := promptCompositor()
terminal, terminalSelected := promptTerminal() terminal, terminalSelected := promptTerminal()
useSystemd := promptSystemd() useSystemd := true
if wmSelected {
if wm == deps.WindowManagerMango {
useSystemd = false
} else {
useSystemd = promptSystemd()
}
}
if !wmSelected && !terminalSelected { if !wmSelected && !terminalSelected {
fmt.Println("No configurations selected. Exiting.") fmt.Println("No configurations selected. Exiting.")
+114
View File
@@ -0,0 +1,114 @@
package main
import (
"context"
"fmt"
"os"
"strings"
"github.com/AvengeMedia/DankMaterialShell/core/internal/privesc"
)
// runit (Void Linux) service helpers. Services live in /etc/sv and are "enabled"
// by symlinking them into the /var/service supervision dir, so the greeter
// commands branch on isRunit() instead of shelling systemctl.
const (
runitSvDir = "/etc/sv"
runitServiceDir = "/var/service"
)
// isRunit reports whether this system is supervised by runit (Void Linux).
func isRunit() bool {
if fi, err := os.Stat("/run/runit"); err == nil && fi.IsDir() {
return true
}
if _, err := os.Stat("/run/systemd/system"); err == nil {
return false
}
if fi, err := os.Stat(runitServiceDir); err == nil && fi.IsDir() {
return true
}
return false
}
func runitServiceInstalled(name string) bool {
fi, err := os.Stat(runitSvDir + "/" + name)
return err == nil && fi.IsDir()
}
func runitServiceEnabled(name string) bool {
_, err := os.Lstat(runitServiceDir + "/" + name)
return err == nil
}
// enableRunitService links a service into /var/service (idempotent).
func enableRunitService(name string) error {
if !runitServiceInstalled(name) {
return fmt.Errorf("runit service %q not found in %s", name, runitSvDir)
}
if runitServiceEnabled(name) {
return nil
}
return privesc.Run(context.Background(), "", "ln", "-sf",
runitSvDir+"/"+name, runitServiceDir+"/"+name)
}
// disableRunitService removes a service's supervision symlink.
func disableRunitService(name string) error {
if !runitServiceEnabled(name) {
return nil
}
return privesc.Run(context.Background(), "", "rm", "-f",
runitServiceDir+"/"+name)
}
// ensureRunitSeat sets up the seat access a Wayland greeter needs on runit (the
// equivalent of logind on systemd): enables seatd and adds the greeter user to
// the seat/video/input groups. Failures are reported but non-fatal.
func ensureRunitSeat(greeterUser string) {
if runitServiceInstalled("seatd") {
if err := enableRunitService("seatd"); err != nil {
fmt.Printf(" ⚠ could not enable seatd: %v\n", err)
} else {
fmt.Println(" ✓ seatd enabled")
}
} else {
fmt.Println(" ⚠ seatd not installed — the greeter compositor needs it for GPU/seat access")
}
if err := privesc.Run(context.Background(), "", "usermod", "-aG", "_seatd,video,input", greeterUser); err != nil {
fmt.Printf(" ⚠ could not add %s to seat groups: %v\n", greeterUser, err)
} else {
fmt.Printf(" ✓ %s added to seat groups (_seatd, video, input)\n", greeterUser)
}
}
// ensureGreetdPamRundir adds pam_rundir to the greetd PAM stack so the post-login
// session gets an XDG_RUNTIME_DIR on systems without logind (Void with seatd).
// Appended outside DMS's managed auth block so it survives `dms greeter sync`.
func ensureGreetdPamRundir() {
const pamPath = "/etc/pam.d/greetd"
data, err := os.ReadFile(pamPath)
if err != nil {
fmt.Printf(" ⚠ could not read %s: %v\n", pamPath, err)
return
}
if strings.Contains(string(data), "pam_rundir") {
return
}
line := "session optional pam_rundir.so"
if err := privesc.Run(context.Background(), "", "sh", "-c",
fmt.Sprintf("printf '%%s\\n' %q >> %s", line, pamPath)); err != nil {
fmt.Printf(" ⚠ could not add pam_rundir to %s: %v\n", pamPath, err)
return
}
fmt.Println(" ✓ pam_rundir added to greetd PAM (provides XDG_RUNTIME_DIR for the session)")
}
// startGreeterHint returns the init-appropriate "start greetd now" command.
func startGreeterHint() string {
if isRunit() {
return " sudo sv up greetd"
}
return " sudo systemctl start greetd"
}
+1 -1
View File
@@ -19,7 +19,7 @@ func init() {
runCmd.Flags().String("log-file", "", "Append logs to this file in addition to stderr (overrides DMS_LOG_FILE)") runCmd.Flags().String("log-file", "", "Append logs to this file in addition to stderr (overrides DMS_LOG_FILE)")
runCmd.Flags().MarkHidden("daemon-child") runCmd.Flags().MarkHidden("daemon-child")
greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd, greeterUninstallCmd) greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd, greeterUninstallCmd, greeterLaunchSessionCmd)
authCmd.AddCommand(authSyncCmd) authCmd.AddCommand(authSyncCmd)
setupCmd.AddCommand(setupBindsCmd, setupLayoutCmd, setupColorsCmd, setupAlttabCmd, setupOutputsCmd, setupCursorCmd, setupWindowrulesCmd) setupCmd.AddCommand(setupBindsCmd, setupLayoutCmd, setupColorsCmd, setupAlttabCmd, setupOutputsCmd, setupCursorCmd, setupWindowrulesCmd)
updateCmd.AddCommand(updateCheckCmd) updateCmd.AddCommand(updateCheckCmd)
+1 -1
View File
@@ -19,7 +19,7 @@ func init() {
runCmd.Flags().String("log-file", "", "Append logs to this file in addition to stderr (overrides DMS_LOG_FILE)") runCmd.Flags().String("log-file", "", "Append logs to this file in addition to stderr (overrides DMS_LOG_FILE)")
runCmd.Flags().MarkHidden("daemon-child") runCmd.Flags().MarkHidden("daemon-child")
greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd, greeterUninstallCmd) greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd, greeterUninstallCmd, greeterLaunchSessionCmd)
authCmd.AddCommand(authSyncCmd) authCmd.AddCommand(authSyncCmd)
setupCmd.AddCommand(setupBindsCmd, setupLayoutCmd, setupColorsCmd, setupAlttabCmd, setupOutputsCmd, setupCursorCmd, setupWindowrulesCmd) setupCmd.AddCommand(setupBindsCmd, setupLayoutCmd, setupColorsCmd, setupAlttabCmd, setupOutputsCmd, setupCursorCmd, setupWindowrulesCmd)
pluginsCmd.AddCommand(pluginsBrowseCmd, pluginsListCmd, pluginsInstallCmd, pluginsUninstallCmd, pluginsUpdateCmd) pluginsCmd.AddCommand(pluginsBrowseCmd, pluginsListCmd, pluginsInstallCmd, pluginsUninstallCmd, pluginsUpdateCmd)
+193 -30
View File
@@ -2,7 +2,9 @@ package main
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io"
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
@@ -192,6 +194,7 @@ func runShellInteractive(session bool) {
} }
}() }()
ensureFontCache()
log.Infof("Spawning quickshell with -p %s", configPath) log.Infof("Spawning quickshell with -p %s", configPath)
cmd := exec.CommandContext(ctx, "qs", "-p", configPath) cmd := exec.CommandContext(ctx, "qs", "-p", configPath)
@@ -227,8 +230,10 @@ func runShellInteractive(session bool) {
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr tracker := &stderrTracker{parent: os.Stderr}
cmd.Stderr = tracker
startTime := time.Now()
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
log.Fatalf("Error starting quickshell: %v", err) log.Fatalf("Error starting quickshell: %v", err)
} }
@@ -277,7 +282,9 @@ func runShellInteractive(session bool) {
case <-errChan: case <-errChan:
cancel() cancel()
os.Remove(socketPath) os.Remove(socketPath)
os.Exit(getProcessExitCode(cmd.ProcessState)) exitCode := getProcessExitCode(cmd.ProcessState)
logStartupFailure(startTime, exitCode, tracker)
os.Exit(exitCode)
case <-time.After(500 * time.Millisecond): case <-time.After(500 * time.Millisecond):
} }
@@ -294,7 +301,9 @@ func runShellInteractive(session bool) {
cmd.Process.Signal(syscall.SIGTERM) cmd.Process.Signal(syscall.SIGTERM)
} }
os.Remove(socketPath) os.Remove(socketPath)
os.Exit(getProcessExitCode(cmd.ProcessState)) exitCode := getProcessExitCode(cmd.ProcessState)
logStartupFailure(startTime, exitCode, tracker)
os.Exit(exitCode)
} }
} }
} }
@@ -434,6 +443,7 @@ func runShellDaemon(session bool) {
} }
}() }()
ensureFontCache()
log.Infof("Spawning quickshell with -p %s", configPath) log.Infof("Spawning quickshell with -p %s", configPath)
cmd := exec.CommandContext(ctx, "qs", "-p", configPath) cmd := exec.CommandContext(ctx, "qs", "-p", configPath)
@@ -478,8 +488,10 @@ func runShellDaemon(session bool) {
cmd.Stdin = devNull cmd.Stdin = devNull
cmd.Stdout = devNull cmd.Stdout = devNull
cmd.Stderr = devNull tracker := &stderrTracker{parent: devNull}
cmd.Stderr = tracker
startTime := time.Now()
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
log.Fatalf("Error starting daemon: %v", err) log.Fatalf("Error starting daemon: %v", err)
} }
@@ -528,7 +540,9 @@ func runShellDaemon(session bool) {
case <-errChan: case <-errChan:
cancel() cancel()
os.Remove(socketPath) os.Remove(socketPath)
os.Exit(getProcessExitCode(cmd.ProcessState)) exitCode := getProcessExitCode(cmd.ProcessState)
logStartupFailure(startTime, exitCode, tracker)
os.Exit(exitCode)
case <-time.After(500 * time.Millisecond): case <-time.After(500 * time.Millisecond):
} }
@@ -543,7 +557,9 @@ func runShellDaemon(session bool) {
cmd.Process.Signal(syscall.SIGTERM) cmd.Process.Signal(syscall.SIGTERM)
} }
os.Remove(socketPath) os.Remove(socketPath)
os.Exit(getProcessExitCode(cmd.ProcessState)) exitCode := getProcessExitCode(cmd.ProcessState)
logStartupFailure(startTime, exitCode, tracker)
os.Exit(exitCode)
} }
} }
} }
@@ -585,12 +601,30 @@ func parseTargetsFromIPCShowOutput(output string) ipcTargets {
return targets return targets
} }
func getShellIPCCompletions(args []string, _ string) []string { func buildQsIPCBaseArgs() ([]string, error) {
cmdArgs := []string{"ipc"} cmdArgs := []string{"ipc"}
switch pid, ok := getFirstDMSPID(); {
case ok:
cmdArgs = append(cmdArgs, "--pid", strconv.Itoa(pid))
default:
if err := findConfig(nil, nil); err != nil {
return nil, err
}
if qsHasAnyDisplay() { if qsHasAnyDisplay() {
cmdArgs = append(cmdArgs, "--any-display") cmdArgs = append(cmdArgs, "--any-display")
} }
cmdArgs = append(cmdArgs, "-p", configPath, "show") cmdArgs = append(cmdArgs, "-p", configPath)
}
return cmdArgs, nil
}
func getShellIPCCompletions(args []string, _ string) []string {
baseArgs, err := buildQsIPCBaseArgs()
if err != nil {
log.Debugf("Error building IPC args for completions: %v", err)
return nil
}
cmdArgs := append(baseArgs, "show")
cmd := exec.Command("qs", cmdArgs...) cmd := exec.Command("qs", cmdArgs...)
var targets ipcTargets var targets ipcTargets
@@ -607,7 +641,7 @@ func getShellIPCCompletions(args []string, _ string) []string {
if len(args) == 0 { if len(args) == 0 {
targetNames := make([]string, 0) targetNames := make([]string, 0)
targetNames = append(targetNames, "call") targetNames = append(targetNames, "call", "list")
for k := range targets { for k := range targets {
targetNames = append(targetNames, k) targetNames = append(targetNames, k)
} }
@@ -680,23 +714,11 @@ func runShellIPCCommand(args []string) {
args = append([]string{"call"}, args...) args = append([]string{"call"}, args...)
} }
cmdArgs := []string{"ipc"} baseArgs, err := buildQsIPCBaseArgs()
if err != nil {
switch pid, ok := getFirstDMSPID(); {
case ok:
cmdArgs = append(cmdArgs, "--pid", strconv.Itoa(pid))
default:
if err := findConfig(nil, nil); err != nil {
log.Fatalf("Error finding config: %v", err) log.Fatalf("Error finding config: %v", err)
} }
// ! TODO - remove check when QS 0.3 is released cmdArgs := append(baseArgs, args...)
if qsHasAnyDisplay() {
cmdArgs = append(cmdArgs, "--any-display")
}
cmdArgs = append(cmdArgs, "-p", configPath)
}
cmdArgs = append(cmdArgs, args...)
cmd := exec.Command("qs", cmdArgs...) cmd := exec.Command("qs", cmdArgs...)
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
@@ -708,19 +730,20 @@ func runShellIPCCommand(args []string) {
} }
func printIPCHelp() { func printIPCHelp() {
fmt.Println("Usage: dms ipc <target> <function> [args...]") fmt.Println("Usage: dms ipc call <target> <function> [args...]")
fmt.Println() fmt.Println()
cmdArgs := []string{"ipc"} baseArgs, err := buildQsIPCBaseArgs()
if qsHasAnyDisplay() { if err != nil {
cmdArgs = append(cmdArgs, "--any-display") printIPCHelpFailure(err)
return
} }
cmdArgs = append(cmdArgs, "-p", configPath, "show") cmdArgs := append(baseArgs, "show")
cmd := exec.Command("qs", cmdArgs...) cmd := exec.Command("qs", cmdArgs...)
output, err := cmd.Output() output, err := cmd.Output()
if err != nil { if err != nil {
fmt.Println("Could not retrieve available IPC targets (is DMS running?)") printIPCHelpFailure(err)
return return
} }
@@ -748,3 +771,143 @@ func printIPCHelp() {
fmt.Printf(" %-16s %s\n", targetName, strings.Join(funcNames, ", ")) fmt.Printf(" %-16s %s\n", targetName, strings.Join(funcNames, ", "))
} }
} }
func printIPCHelpFailure(err error) {
fmt.Println("Could not retrieve IPC targets.")
if err != nil {
fmt.Printf(" %v\n", err)
}
fmt.Println()
fmt.Println(" Full docs: https://danklinux.com/docs/dankmaterialshell/keybinds-ipc")
fmt.Println(" Try: dms ipc call <target> <function>")
}
// ensureFontCache rebuilds the fontconfig cache if user-configured fonts are missing while skipping defaults
func ensureFontCache() {
if _, err := exec.LookPath("fc-list"); err != nil {
return
}
if _, err := exec.LookPath("fc-cache"); err != nil {
return
}
var fontsToCheck []string
if configDir, err := os.UserConfigDir(); err == nil {
settingsPath := filepath.Join(configDir, "DankMaterialShell", "settings.json")
if data, err := os.ReadFile(settingsPath); err == nil {
var settings struct {
FontFamily string `json:"fontFamily"`
MonoFontFamily string `json:"monoFontFamily"`
}
if err := json.Unmarshal(data, &settings); err == nil {
if settings.FontFamily != "" && settings.FontFamily != "Inter Variable" {
fontsToCheck = append(fontsToCheck, settings.FontFamily)
}
if settings.MonoFontFamily != "" && settings.MonoFontFamily != "Fira Code" {
fontsToCheck = append(fontsToCheck, settings.MonoFontFamily)
}
}
}
}
if len(fontsToCheck) == 0 {
return
}
output, err := exec.Command("fc-list", ":", "family").Output()
if err != nil || len(strings.TrimSpace(string(output))) == 0 {
log.Warnf("Font cache appears empty or corrupt, rebuilding...")
rebuildFontCache()
return
}
cacheFonts := strings.ToLower(string(output))
var missing []string
for _, font := range fontsToCheck {
if !fontInCache(strings.ToLower(font), cacheFonts) {
missing = append(missing, font)
}
}
if len(missing) > 0 {
log.Warnf("Font(s) not found in cache: %s — rebuilding...", strings.Join(missing, ", "))
rebuildFontCache()
}
}
func fontInCache(target, cache string) bool {
for _, line := range strings.Split(cache, "\n") {
for _, fam := range strings.Split(strings.TrimSpace(line), ",") {
if strings.TrimSpace(fam) == target {
return true
}
}
}
return false
}
func rebuildFontCache() {
cmd := exec.Command("fc-cache", "-f")
if output, err := cmd.CombinedOutput(); err != nil {
log.Warnf("Failed to rebuild font cache: %v\n%s", err, string(output))
} else {
log.Infof("Font cache rebuilt successfully")
}
}
type stderrTracker struct {
mu sync.Mutex
buf strings.Builder
parent io.Writer
}
func (s *stderrTracker) Write(p []byte) (n int, err error) {
s.mu.Lock()
defer s.mu.Unlock()
if s.buf.Len() < 8192 {
s.buf.Write(p)
}
if s.parent != nil {
return s.parent.Write(p)
}
return len(p), nil
}
func (s *stderrTracker) String() string {
s.mu.Lock()
defer s.mu.Unlock()
return s.buf.String()
}
// logStartupFailure logs diagnostic advice if qs crashes within 5s of launch.
func logStartupFailure(startTime time.Time, exitCode int, tracker *stderrTracker) {
if time.Since(startTime) >= 5*time.Second || exitCode == 0 || exitCode > 128 {
return
}
if containsFontCrashSignature(tracker.String()) {
log.Errorf("DMS startup failed due to a potential font/rendering crash. Try running 'fc-cache -fv' and restarting DMS.")
} else {
log.Errorf("DMS startup failed (exit code %d). Run 'dms doctor' for more diagnostics.", exitCode)
}
}
func containsFontCrashSignature(logStr string) bool {
logStr = strings.ToLower(logStr)
signatures := []string{
"fontconfig",
"freetype",
"ft_load_glyph",
"ft_face",
"fc-list",
"fc-cache",
"glyph",
"typeface",
}
for _, sig := range signatures {
if strings.Contains(logStr, sig) {
return true
}
}
return false
}
+12
View File
@@ -520,6 +520,18 @@ func TestHyprlandConfigStructure(t *testing.T) {
assert.Contains(t, HyprlandLuaConfig, "input =") assert.Contains(t, HyprlandLuaConfig, "input =")
} }
func TestMangoConfigStructure(t *testing.T) {
assert.Contains(t, MangoConfig, "exec-once=dms run")
assert.NotContains(t, MangoConfig, "exec_once=dms run")
assert.Contains(t, MangoConfig, "source=./dms/binds.conf")
assert.Contains(t, MangoBindsConfig, "bind=SUPER,H,focusdir,left")
assert.Contains(t, MangoBindsConfig, "bind=SUPER,J,focusdir,down")
assert.Contains(t, MangoBindsConfig, "bind=SUPER,K,focusdir,up")
assert.Contains(t, MangoBindsConfig, "bind=SUPER,L,focusdir,right")
assert.Contains(t, MangoBindsConfig, "gesturebind=none,right,3,viewtoleft_have_client")
assert.Contains(t, MangoBindsConfig, "gesturebind=none,left,3,viewtoright_have_client")
}
func TestGhosttyConfigStructure(t *testing.T) { func TestGhosttyConfigStructure(t *testing.T) {
assert.Contains(t, GhosttyConfig, "window-decoration = false") assert.Contains(t, GhosttyConfig, "window-decoration = false")
assert.Contains(t, GhosttyConfig, "background-opacity = 1.0") assert.Contains(t, GhosttyConfig, "background-opacity = 1.0")
+13 -55
View File
@@ -1,7 +1,6 @@
# DMS default keybinds (MangoWM) — managed by DMS, regenerated by `dms setup`. # DMS default keybinds (MangoWM) — managed by DMS, regenerated by `dms setup`.
# Format: bind=MODS,key,action[,args] # Format: bind=MODS,key,action[,args]
# Descriptions go on the line ABOVE each bind (mango does not strip inline # Put bind descriptions above bind lines; inline # comments break Mango spawn args.
# comments — a trailing `# ...` would be passed to spawn as extra arguments).
# === Application Launchers === # === Application Launchers ===
# Open Terminal # Open Terminal
@@ -52,131 +51,90 @@ bind=CTRL,Print,spawn,dms screenshot full
bind=ALT,Print,spawn,dms screenshot window bind=ALT,Print,spawn,dms screenshot window
# === Audio Controls === # === Audio Controls ===
# Volume Up
bind=none,XF86AudioRaiseVolume,spawn,dms ipc call audio increment 3 bind=none,XF86AudioRaiseVolume,spawn,dms ipc call audio increment 3
# Volume Down
bind=none,XF86AudioLowerVolume,spawn,dms ipc call audio decrement 3 bind=none,XF86AudioLowerVolume,spawn,dms ipc call audio decrement 3
# Mute Output
bind=none,XF86AudioMute,spawn,dms ipc call audio mute bind=none,XF86AudioMute,spawn,dms ipc call audio mute
# Mute Microphone
bind=none,XF86AudioMicMute,spawn,dms ipc call audio micmute bind=none,XF86AudioMicMute,spawn,dms ipc call audio micmute
# Play/Pause
bind=none,XF86AudioPlay,spawn,dms ipc call mpris playPause bind=none,XF86AudioPlay,spawn,dms ipc call mpris playPause
# Play/Pause
bind=none,XF86AudioPause,spawn,dms ipc call mpris playPause bind=none,XF86AudioPause,spawn,dms ipc call mpris playPause
# Previous Track
bind=none,XF86AudioPrev,spawn,dms ipc call mpris previous bind=none,XF86AudioPrev,spawn,dms ipc call mpris previous
# Next Track
bind=none,XF86AudioNext,spawn,dms ipc call mpris next bind=none,XF86AudioNext,spawn,dms ipc call mpris next
# === Brightness Controls === # === Brightness Controls ===
# Brightness Up
bind=none,XF86MonBrightnessUp,spawn,dms ipc call brightness increment 5 bind=none,XF86MonBrightnessUp,spawn,dms ipc call brightness increment 5
# Brightness Down
bind=none,XF86MonBrightnessDown,spawn,dms ipc call brightness decrement 5 bind=none,XF86MonBrightnessDown,spawn,dms ipc call brightness decrement 5
# === Window Management === # === Window Management ===
# Close Window # Close Window
bind=SUPER,q,killclient, bind=SUPER,q,killclient,
# Toggle Fullscreen
bind=SUPER,f,togglefullscreen, bind=SUPER,f,togglefullscreen,
# Toggle Maximize
bind=SUPER,a,togglemaximizescreen, bind=SUPER,a,togglemaximizescreen,
# Toggle Floating
bind=SUPER+SHIFT,space,togglefloating, bind=SUPER+SHIFT,space,togglefloating,
# Toggle Overview
bind=SUPER,o,toggleoverview bind=SUPER,o,toggleoverview
bind=ALT,Tab,toggleoverview bind=ALT,Tab,toggleoverview
# Exit Compositor # Exit Compositor
bind=SUPER+SHIFT,e,quit, bind=SUPER+SHIFT,e,quit,
# === Focus Navigation === # === Focus Navigation ===
# Focus Next Window
bind=SUPER,Tab,focusstack,next bind=SUPER,Tab,focusstack,next
# Focus Previous Window
bind=SUPER+SHIFT,Tab,focusstack,prev bind=SUPER+SHIFT,Tab,focusstack,prev
# Focus Left
bind=SUPER,Left,focusdir,left bind=SUPER,Left,focusdir,left
# Focus Right bind=SUPER,H,focusdir,left
bind=SUPER,Right,focusdir,right bind=SUPER,Right,focusdir,right
# Focus Up bind=SUPER,L,focusdir,right
bind=SUPER,Up,focusdir,up bind=SUPER,Up,focusdir,up
# Focus Down bind=SUPER,K,focusdir,up
bind=SUPER,Down,focusdir,down bind=SUPER,Down,focusdir,down
bind=SUPER,J,focusdir,down
# === Window Movement === # === Window Movement ===
# Move Window Left
bind=SUPER+SHIFT,Left,exchange_client,left bind=SUPER+SHIFT,Left,exchange_client,left
# Move Window Right
bind=SUPER+SHIFT,Right,exchange_client,right bind=SUPER+SHIFT,Right,exchange_client,right
# Move Window Up
bind=SUPER+SHIFT,Up,exchange_client,up bind=SUPER+SHIFT,Up,exchange_client,up
# Move Window Down
bind=SUPER+SHIFT,Down,exchange_client,down bind=SUPER+SHIFT,Down,exchange_client,down
bind=SUPER+SHIFT,H,exchange_client,left
bind=SUPER+SHIFT,L,exchange_client,right
bind=SUPER+SHIFT,K,exchange_client,up
bind=SUPER+SHIFT,J,exchange_client,down
# === Monitor Navigation === # === Monitor Navigation ===
# Focus Monitor Left
bind=SUPER+ALT,Left,focusmon,left bind=SUPER+ALT,Left,focusmon,left
# Focus Monitor Right
bind=SUPER+ALT,Right,focusmon,right bind=SUPER+ALT,Right,focusmon,right
# Move to Monitor Left
bind=SUPER+ALT+SHIFT,Left,tagmon,left bind=SUPER+ALT+SHIFT,Left,tagmon,left
# Move to Monitor Right
bind=SUPER+ALT+SHIFT,Right,tagmon,right bind=SUPER+ALT+SHIFT,Right,tagmon,right
# === Layout === # === Layout ===
# Cycle Layout # Cycle Layout - Gaps, Floating, Tiling
bind=SUPER,j,switch_layout bind=SUPER+ALT,j,switch_layout
# Increase Gaps
bind=SUPER+SHIFT,equal,incgaps,1 bind=SUPER+SHIFT,equal,incgaps,1
# Decrease Gaps
bind=SUPER+SHIFT,minus,incgaps,-1 bind=SUPER+SHIFT,minus,incgaps,-1
# === Tags (1-9): view tag === # === Tags (1-9): view tag ===
# View Tag 1
bind=SUPER,1,view,1 bind=SUPER,1,view,1
# View Tag 2
bind=SUPER,2,view,2 bind=SUPER,2,view,2
# View Tag 3
bind=SUPER,3,view,3 bind=SUPER,3,view,3
# View Tag 4
bind=SUPER,4,view,4 bind=SUPER,4,view,4
# View Tag 5
bind=SUPER,5,view,5 bind=SUPER,5,view,5
# View Tag 6
bind=SUPER,6,view,6 bind=SUPER,6,view,6
# View Tag 7
bind=SUPER,7,view,7 bind=SUPER,7,view,7
# View Tag 8
bind=SUPER,8,view,8 bind=SUPER,8,view,8
# View Tag 9
bind=SUPER,9,view,9 bind=SUPER,9,view,9
# === Tags (1-9): move focused window to tag === # === Tags (1-9): move focused window to tag ===
# Move to Tag 1
bind=SUPER+SHIFT,1,tag,1 bind=SUPER+SHIFT,1,tag,1
# Move to Tag 2
bind=SUPER+SHIFT,2,tag,2 bind=SUPER+SHIFT,2,tag,2
# Move to Tag 3
bind=SUPER+SHIFT,3,tag,3 bind=SUPER+SHIFT,3,tag,3
# Move to Tag 4
bind=SUPER+SHIFT,4,tag,4 bind=SUPER+SHIFT,4,tag,4
# Move to Tag 5
bind=SUPER+SHIFT,5,tag,5 bind=SUPER+SHIFT,5,tag,5
# Move to Tag 6
bind=SUPER+SHIFT,6,tag,6 bind=SUPER+SHIFT,6,tag,6
# Move to Tag 7
bind=SUPER+SHIFT,7,tag,7 bind=SUPER+SHIFT,7,tag,7
# Move to Tag 8
bind=SUPER+SHIFT,8,tag,8 bind=SUPER+SHIFT,8,tag,8
# Move to Tag 9
bind=SUPER+SHIFT,9,tag,9 bind=SUPER+SHIFT,9,tag,9
# === Touchpad Gestures === # === Touchpad Gestures ===
# Syntax: gesturebind=MODIFIERS,DIRECTION,FINGERS,COMMAND,PARAMETERS
# 3-finger horizontal swipe: switch between occupied workspaces # 3-finger horizontal swipe: switch between occupied workspaces
gesturebind=none,left,3,viewtoleft_have_client gesturebind=none,right,3,viewtoleft_have_client
gesturebind=none,right,3,viewtoright_have_client gesturebind=none,left,3,viewtoright_have_client
# 4-finger vertical swipe: toggle the overview # 4-finger vertical swipe: toggle the overview
gesturebind=none,up,4,toggleoverview gesturebind=none,up,4,toggleoverview
gesturebind=none,down,4,toggleoverview gesturebind=none,down,4,toggleoverview
+2 -2
View File
@@ -5,10 +5,10 @@
env=XDG_CURRENT_DESKTOP,mango env=XDG_CURRENT_DESKTOP,mango
env=XDG_SESSION_TYPE,wayland env=XDG_SESSION_TYPE,wayland
# exec_once runs only at startup. Do NOT use exec= for the shell: mango re-runs # exec-once runs only at startup. Do NOT use exec= for the shell: mango re-runs
# every exec= on each config reload, and DMS reloads the config, which would # every exec= on each config reload, and DMS reloads the config, which would
# spawn a new shell on every reload. # spawn a new shell on every reload.
exec_once=dms run exec-once=dms run
source=./dms/colors.conf source=./dms/colors.conf
source=./dms/layout.conf source=./dms/layout.conf
+28 -30
View File
@@ -233,24 +233,39 @@ func stripDesktopExecCodes(execLine string) string {
return strings.Join(cleaned, " ") return strings.Join(cleaned, " ")
} }
func formatInitialSessionCommand(sessionExec string) string { func shellQuote(value string) string {
execLine := strings.TrimSpace(stripDesktopExecCodes(sessionExec)) return "'" + strings.ReplaceAll(value, "'", "'\\''") + "'"
if execLine == "" { }
func stableDMSCommand() string {
for _, candidate := range []string{"/usr/bin/dms", "/usr/local/bin/dms"} {
info, err := os.Stat(candidate)
if err == nil && !info.IsDir() && info.Mode()&0o111 != 0 {
return candidate
}
}
return "dms"
}
func formatInitialSessionCommand(cacheDir string) string {
cacheDir = strings.TrimSpace(cacheDir)
if cacheDir == "" {
return `command = ""` return `command = ""`
} }
escaped := strings.ReplaceAll(execLine, `'`, `'\''`) launcher := fmt.Sprintf("%s greeter launch-session --from-memory --cache-dir %s", stableDMSCommand(), shellQuote(cacheDir))
escaped := strings.ReplaceAll(launcher, `'`, `'\''`)
inner := fmt.Sprintf("env XDG_SESSION_TYPE=wayland sh -c 'exec %s'", escaped) inner := fmt.Sprintf("env XDG_SESSION_TYPE=wayland sh -c 'exec %s'", escaped)
tomlEscaped := strings.ReplaceAll(inner, `\`, `\\`) tomlEscaped := strings.ReplaceAll(inner, `\`, `\\`)
tomlEscaped = strings.ReplaceAll(tomlEscaped, `"`, `\"`) tomlEscaped = strings.ReplaceAll(tomlEscaped, `"`, `\"`)
return fmt.Sprintf(`command = "%s"`, tomlEscaped) return fmt.Sprintf(`command = "%s"`, tomlEscaped)
} }
func upsertInitialSession(configContent, loginUser, sessionExec string, enabled bool) string { func upsertInitialSession(configContent, loginUser, cacheDir string, enabled bool) string {
if !enabled { if !enabled {
return removeTomlSection(configContent, "initial_session") return removeTomlSection(configContent, "initial_session")
} }
commandLine := formatInitialSessionCommand(sessionExec) commandLine := formatInitialSessionCommand(cacheDir)
lines := strings.Split(configContent, "\n") lines := strings.Split(configContent, "\n")
var out []string var out []string
@@ -330,6 +345,7 @@ type greeterAutoLoginConfig struct {
type greeterAutoLoginMemory struct { type greeterAutoLoginMemory struct {
LastSuccessfulUser string `json:"lastSuccessfulUser"` LastSuccessfulUser string `json:"lastSuccessfulUser"`
LastSessionID string `json:"lastSessionId"` LastSessionID string `json:"lastSessionId"`
LastSessionDesktopID string `json:"lastSessionDesktopId"`
LastSessionExec string `json:"lastSessionExec"` LastSessionExec string `json:"lastSessionExec"`
AutoLoginEnabled bool `json:"autoLoginEnabled"` AutoLoginEnabled bool `json:"autoLoginEnabled"`
} }
@@ -381,7 +397,7 @@ func execFromDesktopFile(path string) (string, error) {
return "", fmt.Errorf("no Exec= line found in %s", path) return "", fmt.Errorf("no Exec= line found in %s", path)
} }
func resolveGreeterAutoLoginState(cacheDir, homeDir string) (enabled bool, loginUser string, sessionExec string, err error) { func resolveGreeterAutoLoginState(cacheDir, homeDir string) (enabled bool, loginUser string, sessionID string, err error) {
settingsPath := filepath.Join(cacheDir, "settings.json") settingsPath := filepath.Join(cacheDir, "settings.json")
if _, statErr := os.Stat(settingsPath); statErr != nil { if _, statErr := os.Stat(settingsPath); statErr != nil {
settingsPath = filepath.Join(homeDir, ".config", "DankMaterialShell", "settings.json") settingsPath = filepath.Join(homeDir, ".config", "DankMaterialShell", "settings.json")
@@ -416,15 +432,9 @@ func resolveGreeterAutoLoginState(cacheDir, homeDir string) (enabled bool, login
loginUser = current.Username loginUser = current.Username
} }
sessionExec = mem.LastSessionExec sessionID = sessionDesktopIDFromMemory(mem)
if sessionExec == "" && mem.LastSessionID != "" {
sessionExec, err = execFromDesktopFile(mem.LastSessionID)
if err != nil {
sessionExec = ""
}
}
return true, loginUser, sessionExec, nil return true, loginUser, sessionID, nil
} }
func writeGreetdConfig(configPath, content string, logFunc func(string), sudoPassword, successMsg string) error { func writeGreetdConfig(configPath, content string, logFunc func(string), sudoPassword, successMsg string) error {
@@ -540,7 +550,7 @@ func readGreeterMemoryFile(memoryPath, sudoPassword string) ([]byte, error) {
} }
func SyncGreetdAutoLogin(cacheDir, homeDir string, logFunc func(string), sudoPassword string) error { func SyncGreetdAutoLogin(cacheDir, homeDir string, logFunc func(string), sudoPassword string) error {
enabled, loginUser, sessionExec, err := resolveGreeterAutoLoginState(cacheDir, homeDir) enabled, loginUser, sessionID, err := resolveGreeterAutoLoginState(cacheDir, homeDir)
if err != nil { if err != nil {
return err return err
} }
@@ -568,7 +578,7 @@ func SyncGreetdAutoLogin(cacheDir, homeDir string, logFunc func(string), sudoPas
return writeGreetdConfig(configPath, newConfig, logFunc, sudoPassword, "✓ Disabled greeter auto-login") return writeGreetdConfig(configPath, newConfig, logFunc, sudoPassword, "✓ Disabled greeter auto-login")
} }
if loginUser == "" || sessionExec == "" { if loginUser == "" || sessionID == "" {
if logFunc != nil { if logFunc != nil {
logFunc("⚠ Greeter auto-login is enabled but user or session is not configured yet. Log in manually once, then run sync.") logFunc("⚠ Greeter auto-login is enabled but user or session is not configured yet. Log in manually once, then run sync.")
} }
@@ -579,7 +589,7 @@ func SyncGreetdAutoLogin(cacheDir, homeDir string, logFunc func(string), sudoPas
return nil return nil
} }
newConfig := upsertInitialSession(configContent, loginUser, sessionExec, true) newConfig := upsertInitialSession(configContent, loginUser, cacheDir, true)
if newConfig == configContent { if newConfig == configContent {
if logFunc != nil { if logFunc != nil {
logFunc(fmt.Sprintf("✓ Greeter auto-login already configured for %s", loginUser)) logFunc(fmt.Sprintf("✓ Greeter auto-login already configured for %s", loginUser))
@@ -2153,18 +2163,6 @@ vt = 1
commandLine := fmt.Sprintf(`command = "%s"`, commandValue) commandLine := fmt.Sprintf(`command = "%s"`, commandValue)
newConfig := upsertDefaultSession(configContent, greeterUser, commandLine) newConfig := upsertDefaultSession(configContent, greeterUser, commandLine)
homeDir, homeErr := os.UserHomeDir()
if homeErr == nil {
enabled, loginUser, sessionExec, resolveErr := resolveGreeterAutoLoginState(GreeterCacheDir, homeDir)
if resolveErr != nil {
logFunc(fmt.Sprintf("⚠ Warning: Failed to resolve greeter auto-login state: %v", resolveErr))
} else if enabled && loginUser != "" && sessionExec != "" {
newConfig = upsertInitialSession(newConfig, loginUser, sessionExec, true)
} else {
newConfig = upsertInitialSession(newConfig, "", "", false)
}
}
if err := writeGreetdConfig(configPath, newConfig, logFunc, sudoPassword, fmt.Sprintf("✓ Updated greetd configuration (user: %s, command: %s)", greeterUser, commandValue)); err != nil { if err := writeGreetdConfig(configPath, newConfig, logFunc, sudoPassword, fmt.Sprintf("✓ Updated greetd configuration (user: %s, command: %s)", greeterUser, commandValue)); err != nil {
return err return err
} }
+70 -13
View File
@@ -111,15 +111,18 @@ command = "/usr/bin/dms-greeter --command niri"
t.Run("inserts initial session", func(t *testing.T) { t.Run("inserts initial session", func(t *testing.T) {
t.Parallel() t.Parallel()
got := upsertInitialSession(baseConfig, "alice", "niri", true) got := upsertInitialSession(baseConfig, "alice", "/var/cache/dms-greeter", true)
if !strings.Contains(got, "[initial_session]") { if !strings.Contains(got, "[initial_session]") {
t.Fatalf("expected [initial_session] section, got:\n%s", got) t.Fatalf("expected [initial_session] section, got:\n%s", got)
} }
if !strings.Contains(got, `user = "alice"`) { if !strings.Contains(got, `user = "alice"`) {
t.Fatalf("expected alice user in initial session, got:\n%s", got) t.Fatalf("expected alice user in initial session, got:\n%s", got)
} }
if !strings.Contains(got, `env XDG_SESSION_TYPE=wayland sh -c 'exec niri'`) { if !strings.Contains(got, `dms greeter launch-session --from-memory --cache-dir`) {
t.Fatalf("expected wrapped session command, got:\n%s", got) t.Fatalf("expected stable launch-session command, got:\n%s", got)
}
if strings.Contains(got, `exec niri`) {
t.Fatalf("initial session must not bake the desktop Exec command, got:\n%s", got)
} }
}) })
@@ -130,12 +133,12 @@ command = "/usr/bin/dms-greeter --command niri"
user = "bob" user = "bob"
command = "old-command" command = "old-command"
` `
got := upsertInitialSession(existing, "alice", "Hyprland", true) got := upsertInitialSession(existing, "alice", "/var/cache/dms-greeter", true)
if strings.Contains(got, `user = "bob"`) { if strings.Contains(got, `user = "bob"`) {
t.Fatalf("expected bob to be replaced, got:\n%s", got) t.Fatalf("expected bob to be replaced, got:\n%s", got)
} }
if !strings.Contains(got, `exec Hyprland`) { if !strings.Contains(got, `dms greeter launch-session --from-memory`) {
t.Fatalf("expected Hyprland command, got:\n%s", got) t.Fatalf("expected launch-session command, got:\n%s", got)
} }
}) })
@@ -179,15 +182,46 @@ func TestResolveGreeterAutoLoginState(t *testing.T) {
}`) }`)
writeTestFile(t, filepath.Join(cacheDir, ".local/state/memory.json"), `{ writeTestFile(t, filepath.Join(cacheDir, ".local/state/memory.json"), `{
"lastSuccessfulUser": "alice", "lastSuccessfulUser": "alice",
"lastSessionExec": "niri" "lastSessionDesktopId": "niri.desktop"
}`) }`)
enabled, loginUser, sessionExec, err := resolveGreeterAutoLoginState(cacheDir, homeDir) enabled, loginUser, sessionID, err := resolveGreeterAutoLoginState(cacheDir, homeDir)
if err != nil { if err != nil {
t.Fatalf("resolveGreeterAutoLoginState returned error: %v", err) t.Fatalf("resolveGreeterAutoLoginState returned error: %v", err)
} }
if !enabled || loginUser != "alice" || sessionExec != "niri" { if !enabled || loginUser != "alice" || sessionID != "niri.desktop" {
t.Fatalf("got enabled=%v user=%q exec=%q", enabled, loginUser, sessionExec) t.Fatalf("got enabled=%v user=%q session=%q", enabled, loginUser, sessionID)
}
}
func TestResolveGreeterAutoLoginStateIgnoresStaleSessionExec(t *testing.T) {
t.Parallel()
cacheDir := t.TempDir()
homeDir := t.TempDir()
writeTestFile(t, filepath.Join(cacheDir, "settings.json"), `{
"greeterAutoLogin": true,
"greeterRememberLastUser": true,
"greeterRememberLastSession": true
}`)
writeTestFile(t, filepath.Join(cacheDir, ".local/state/memory.json"), `{
"lastSuccessfulUser": "alice",
"lastSessionId": "/nix/store/old-session/share/wayland-sessions/example.desktop",
"lastSessionExec": "/nix/store/old-session/bin/start-example-session"
}`)
enabled, loginUser, sessionID, err := resolveGreeterAutoLoginState(cacheDir, homeDir)
if err != nil {
t.Fatalf("resolveGreeterAutoLoginState returned error: %v", err)
}
if !enabled || loginUser != "alice" || sessionID != "example.desktop" {
t.Fatalf("got enabled=%v user=%q session=%q", enabled, loginUser, sessionID)
}
got := upsertInitialSession("", loginUser, cacheDir, true)
if strings.Contains(got, "/nix/store/old-session") {
t.Fatalf("initial session must not include stale store path, got:\n%s", got)
} }
} }
@@ -208,12 +242,35 @@ func TestResolveGreeterAutoLoginStateIgnoresMemoryFlag(t *testing.T) {
"lastSessionExec": "niri" "lastSessionExec": "niri"
}`) }`)
enabled, loginUser, sessionExec, err := resolveGreeterAutoLoginState(cacheDir, homeDir) enabled, loginUser, sessionID, err := resolveGreeterAutoLoginState(cacheDir, homeDir)
if err != nil { if err != nil {
t.Fatalf("resolveGreeterAutoLoginState returned error: %v", err) t.Fatalf("resolveGreeterAutoLoginState returned error: %v", err)
} }
if enabled || loginUser != "" || sessionExec != "" { if enabled || loginUser != "" || sessionID != "" {
t.Fatalf("expected disabled with empty user/exec, got enabled=%v user=%q exec=%q", enabled, loginUser, sessionExec) t.Fatalf("expected disabled with empty user/session, got enabled=%v user=%q session=%q", enabled, loginUser, sessionID)
}
}
func TestResolveSessionExecInDirs(t *testing.T) {
t.Parallel()
oldDir := filepath.Join(t.TempDir(), "wayland-sessions")
newDir := filepath.Join(t.TempDir(), "wayland-sessions")
writeTestFile(t, filepath.Join(oldDir, "example.desktop"), `[Desktop Entry]
Name=Example Session
Exec=/nix/store/old-session/bin/start-example-session
`)
writeTestFile(t, filepath.Join(newDir, "example.desktop"), `[Desktop Entry]
Name=Example Session
Exec=/run/current-system/sw/bin/start-example-session
`)
got, err := resolveSessionExecInDirs("example.desktop", []string{newDir, oldDir})
if err != nil {
t.Fatalf("resolveSessionExecInDirs returned error: %v", err)
}
if got != "/run/current-system/sw/bin/start-example-session" {
t.Fatalf("resolveSessionExecInDirs = %q", got)
} }
} }
+122
View File
@@ -0,0 +1,122 @@
package greeter
import (
"fmt"
"os"
"path/filepath"
"strings"
"syscall"
)
func sessionDesktopIDFromPath(path string) string {
id := strings.TrimSpace(path)
if id == "" {
return ""
}
if strings.ContainsAny(id, "/\\") {
id = filepath.Base(id)
}
if id == "" {
return ""
}
if !strings.HasSuffix(id, ".desktop") {
id += ".desktop"
}
return id
}
func sessionDesktopIDFromMemory(mem greeterAutoLoginMemory) string {
if id := sessionDesktopIDFromPath(mem.LastSessionDesktopID); id != "" {
return id
}
return sessionDesktopIDFromPath(mem.LastSessionID)
}
func sessionDesktopDirs() []string {
seen := make(map[string]bool)
dirs := make([]string, 0, 8)
addBase := func(base string) {
base = strings.TrimSpace(base)
if base == "" {
return
}
for _, sub := range []string{"wayland-sessions", "xsessions"} {
dir := filepath.Join(base, sub)
if seen[dir] {
continue
}
seen[dir] = true
dirs = append(dirs, dir)
}
}
if dataHome := os.Getenv("XDG_DATA_HOME"); dataHome != "" {
addBase(dataHome)
} else if home, err := os.UserHomeDir(); err == nil && home != "" {
addBase(filepath.Join(home, ".local", "share"))
}
if dataDirs := os.Getenv("XDG_DATA_DIRS"); dataDirs != "" {
for _, dir := range strings.Split(dataDirs, ":") {
addBase(dir)
}
} else {
addBase("/usr/local/share")
addBase("/usr/share")
}
return dirs
}
func ResolveSessionExec(sessionID string) (string, error) {
return resolveSessionExecInDirs(sessionID, sessionDesktopDirs())
}
func resolveSessionExecInDirs(sessionID string, dirs []string) (string, error) {
id := sessionDesktopIDFromPath(sessionID)
if id == "" {
return "", fmt.Errorf("session id is empty")
}
for _, dir := range dirs {
path := filepath.Join(dir, id)
execLine, err := execFromDesktopFile(path)
if err == nil {
return execLine, nil
}
if !os.IsNotExist(err) {
return "", err
}
}
return "", fmt.Errorf("session desktop file %q was not found", id)
}
func LaunchSessionByID(sessionID string) error {
execLine, err := ResolveSessionExec(sessionID)
if err != nil {
return err
}
execLine = strings.TrimSpace(stripDesktopExecCodes(execLine))
if execLine == "" {
return fmt.Errorf("session %q has an empty Exec command", sessionID)
}
env := append(os.Environ(), "XDG_SESSION_TYPE=wayland")
return syscall.Exec("/bin/sh", []string{"sh", "-c", "exec " + execLine}, env)
}
func LaunchSessionFromMemory(cacheDir, homeDir string) error {
enabled, _, sessionID, err := resolveGreeterAutoLoginState(cacheDir, homeDir)
if err != nil {
return err
}
if !enabled {
return fmt.Errorf("greeter auto-login is disabled")
}
if sessionID == "" {
return fmt.Errorf("greeter auto-login has no remembered session")
}
return LaunchSessionByID(sessionID)
}
+13 -1
View File
@@ -190,9 +190,13 @@ func (h *HyprlandProvider) formatRawAction(dispatcher, params string) string {
} }
func (h *HyprlandProvider) formatKey(kb *HyprlandKeyBinding) string { func (h *HyprlandProvider) formatKey(kb *HyprlandKeyBinding) string {
key := kb.Key
if canonical, ok := hyprlandScrollToCanonical(key); ok {
key = canonical
}
parts := make([]string, 0, len(kb.Mods)+1) parts := make([]string, 0, len(kb.Mods)+1)
parts = append(parts, kb.Mods...) parts = append(parts, kb.Mods...)
parts = append(parts, kb.Key) parts = append(parts, key)
return strings.Join(parts, "+") return strings.Join(parts, "+")
} }
@@ -411,6 +415,9 @@ func normalizeLuaBindKeyPart(part string) string {
case "alt", "mod1": case "alt", "mod1":
return "ALT" return "ALT"
} }
if native, ok := hyprlandScrollToNative(part); ok {
return native
}
if len(part) == 1 { if len(part) == 1 {
return strings.ToUpper(part) return strings.ToUpper(part)
} }
@@ -1130,6 +1137,11 @@ func parseLuaUnbindLine(line string) (string, bool) {
func luaKeyComboToInternalKey(combo string) string { func luaKeyComboToInternalKey(combo string) string {
parts := strings.Fields(strings.ReplaceAll(strings.ReplaceAll(combo, "+", " "), " ", " ")) parts := strings.Fields(strings.ReplaceAll(strings.ReplaceAll(combo, "+", " "), " ", " "))
for i, part := range parts {
if canonical, ok := hyprlandScrollToCanonical(part); ok {
parts[i] = canonical
}
}
return strings.Join(parts, "+") return strings.Join(parts, "+")
} }
@@ -347,9 +347,13 @@ func (p *HyprlandParser) buildDMSStatus() *HyprlandDMSStatus {
} }
func (p *HyprlandParser) formatBindKey(kb *HyprlandKeyBinding) string { func (p *HyprlandParser) formatBindKey(kb *HyprlandKeyBinding) string {
key := kb.Key
if canonical, ok := hyprlandScrollToCanonical(key); ok {
key = canonical
}
parts := make([]string, 0, len(kb.Mods)+1) parts := make([]string, 0, len(kb.Mods)+1)
parts = append(parts, kb.Mods...) parts = append(parts, kb.Mods...)
parts = append(parts, kb.Key) parts = append(parts, key)
return strings.Join(parts, "+") return strings.Join(parts, "+")
} }
@@ -486,6 +486,61 @@ hl.bind("SUPER + 1", hl.dsp.exec_cmd("hyprctl dispatch workspace 1"))
} }
} }
func TestHyprlandSetBindTranslatesScrollWheelToMouse(t *testing.T) {
tmpDir := t.TempDir()
dmsDir := filepath.Join(tmpDir, "dms")
if err := os.MkdirAll(dmsDir, 0o755); err != nil {
t.Fatal(err)
}
bindsUser := filepath.Join(dmsDir, "binds-user.lua")
if err := os.WriteFile(bindsUser, []byte("-- DMS user keybind overrides\n"), 0o644); err != nil {
t.Fatal(err)
}
provider := NewHyprlandProvider(tmpDir)
if err := provider.SetBind("SUPER + WheelScrollDown", "workspace 1", "", nil); err != nil {
t.Fatal(err)
}
got := readFile(t, bindsUser)
if !strings.Contains(got, `hl.bind("SUPER + mouse_down"`) {
t.Fatalf("expected scroll key translated to mouse_down, got:\n%s", got)
}
if strings.Contains(got, "WheelScroll") {
t.Fatalf("expected no raw niri scroll keysym in hyprland output, got:\n%s", got)
}
if err := provider.SetBind("SUPER + WheelScrollDown", "workspace 2", "", nil); err != nil {
t.Fatal(err)
}
got = readFile(t, bindsUser)
if strings.Count(got, `hl.bind("SUPER + mouse_down"`) != 1 {
t.Fatalf("expected exactly one mouse_down bind after re-save, got:\n%s", got)
}
}
func TestHyprlandScrollWheelRoundTrips(t *testing.T) {
for native, canonical := range map[string]string{
"mouse_up": "WheelScrollUp",
"mouse_down": "WheelScrollDown",
"mouse_left": "WheelScrollLeft",
"mouse_right": "WheelScrollRight",
} {
if got := luaKeyComboToInternalKey("SUPER + " + native); got != "SUPER+"+canonical {
t.Errorf("luaKeyComboToInternalKey(%q) = %q, want SUPER+%s", native, got, canonical)
}
}
}
func readFile(t *testing.T, path string) string {
t.Helper()
data, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
return string(data)
}
func TestHyprlandRemoveBindReplacesExistingOverrideWithNegativeOverride(t *testing.T) { func TestHyprlandRemoveBindReplacesExistingOverrideWithNegativeOverride(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
dmsDir := filepath.Join(tmpDir, "dms") dmsDir := filepath.Join(tmpDir, "dms")
+263 -29
View File
@@ -7,6 +7,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/AvengeMedia/DankMaterialShell/core/internal/config"
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds" "github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
"github.com/AvengeMedia/DankMaterialShell/core/internal/utils" "github.com/AvengeMedia/DankMaterialShell/core/internal/utils"
) )
@@ -228,11 +229,23 @@ func (m *MangoWCProvider) SetBind(key, action, description string, options map[s
} }
normalizedKey := strings.ToLower(key) normalizedKey := strings.ToLower(key)
prefix := "bind"
if existing, ok := existingBinds[normalizedKey]; ok && existing.Prefix != "" {
prefix = existing.Prefix
}
if optionPrefix := m.bindPrefixFromOptions(options); optionPrefix != "" {
prefix = optionPrefix
}
if _, leaf := m.parseKeyString(key); isScrollKey(leaf) {
prefix = mangowcAxisBindPrefix
}
existingBinds[normalizedKey] = &mangowcOverrideBind{ existingBinds[normalizedKey] = &mangowcOverrideBind{
Key: key, Key: key,
Action: action, Action: action,
Description: description, Description: description,
Options: options, Options: options,
Prefix: prefix,
} }
return m.writeOverrideBinds(existingBinds) return m.writeOverrideBinds(existingBinds)
@@ -246,7 +259,7 @@ func (m *MangoWCProvider) RemoveBind(key string) error {
normalizedKey := strings.ToLower(key) normalizedKey := strings.ToLower(key)
delete(existingBinds, normalizedKey) delete(existingBinds, normalizedKey)
return m.writeOverrideBinds(existingBinds) return m.writeOverrideBindsWithRemoved(existingBinds, map[string]bool{normalizedKey: true})
} }
func (m *MangoWCProvider) ResetBind(key string) error { func (m *MangoWCProvider) ResetBind(key string) error {
@@ -258,6 +271,7 @@ type mangowcOverrideBind struct {
Action string Action string
Description string Description string
Options map[string]any Options map[string]any
Prefix string
} }
func (m *MangoWCProvider) loadOverrideBinds() (map[string]*mangowcOverrideBind, error) { func (m *MangoWCProvider) loadOverrideBinds() (map[string]*mangowcOverrideBind, error) {
@@ -272,60 +286,106 @@ func (m *MangoWCProvider) loadOverrideBinds() (map[string]*mangowcOverrideBind,
return nil, err return nil, err
} }
lines := strings.Split(string(data), "\n") var pendingComment string
for _, line := range lines { for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line) trimmed := strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") { if trimmed == "" {
pendingComment = ""
continue
}
if strings.HasPrefix(trimmed, "#") {
pendingComment = strings.TrimSpace(strings.TrimPrefix(trimmed, "#"))
if isMangoWCSectionComment(pendingComment) {
pendingComment = ""
}
continue continue
} }
if !strings.HasPrefix(line, "bind") { bind, ok := m.parseOverrideBindLine(line, pendingComment)
pendingComment = ""
if !ok || bind == nil {
continue continue
} }
parts := strings.SplitN(line, "=", 2) binds[strings.ToLower(bind.Key)] = bind
}
return binds, nil
}
func (m *MangoWCProvider) parseOverrideBindLine(line, precedingComment string) (*mangowcOverrideBind, bool) {
trimmed := strings.TrimSpace(line)
parts := strings.SplitN(trimmed, "=", 2)
if len(parts) < 2 { if len(parts) < 2 {
continue return nil, false
}
prefix := strings.TrimSpace(parts[0])
if !m.isBindPrefix(prefix) {
return nil, false
} }
content := strings.TrimSpace(parts[1]) content := strings.TrimSpace(parts[1])
commentParts := strings.SplitN(content, "#", 2) commentParts := strings.SplitN(content, "#", 2)
bindContent := strings.TrimSpace(commentParts[0]) bindContent := strings.TrimSpace(commentParts[0])
var comment string description := strings.TrimSpace(precedingComment)
if isMangoWCSectionComment(description) {
description = ""
}
if len(commentParts) > 1 { if len(commentParts) > 1 {
comment = strings.TrimSpace(commentParts[1]) description = strings.TrimSpace(commentParts[1])
}
if strings.HasPrefix(description, MangoWCHideComment) {
return nil, true
} }
fields := strings.SplitN(bindContent, ",", 4) fields := strings.SplitN(bindContent, ",", 4)
if len(fields) < 3 { if len(fields) < 3 {
continue return nil, false
} }
mods := strings.TrimSpace(fields[0]) mods := strings.TrimSpace(fields[0])
keyName := strings.TrimSpace(fields[1]) keyName := strings.TrimSpace(fields[1])
command := strings.TrimSpace(fields[2]) command := strings.TrimSpace(fields[2])
if prefix == mangowcAxisBindPrefix {
if canonical, ok := mangowcDirectionToScroll(keyName); ok {
keyName = canonical
}
}
var params string var params string
if len(fields) > 3 { if len(fields) > 3 {
params = strings.TrimSpace(fields[3]) params = strings.TrimSpace(fields[3])
} }
keyStr := m.buildKeyString(mods, keyName)
normalizedKey := strings.ToLower(keyStr)
action := command action := command
if params != "" { if params != "" {
action = command + " " + params action = command + " " + params
} }
binds[normalizedKey] = &mangowcOverrideBind{ return &mangowcOverrideBind{
Key: keyStr, Key: m.buildKeyString(mods, keyName),
Action: action, Action: action,
Description: comment, Description: description,
} Prefix: prefix,
}, true
} }
return binds, nil func (m *MangoWCProvider) isBindPrefix(prefix string) bool {
if prefix == mangowcAxisBindPrefix {
return true
}
if !strings.HasPrefix(prefix, "bind") {
return false
}
for _, ch := range strings.TrimPrefix(prefix, "bind") {
if !strings.ContainsRune("lsrp", ch) {
return false
}
}
return true
} }
func (m *MangoWCProvider) buildKeyString(mods, key string) string { func (m *MangoWCProvider) buildKeyString(mods, key string) string {
@@ -362,21 +422,113 @@ func (m *MangoWCProvider) getBindSortPriority(action string) int {
} }
func (m *MangoWCProvider) writeOverrideBinds(binds map[string]*mangowcOverrideBind) error { func (m *MangoWCProvider) writeOverrideBinds(binds map[string]*mangowcOverrideBind) error {
return m.writeOverrideBindsWithRemoved(binds, nil)
}
func (m *MangoWCProvider) writeOverrideBindsWithRemoved(binds map[string]*mangowcOverrideBind, removed map[string]bool) error {
overridePath := m.GetOverridePath() overridePath := m.GetOverridePath()
content := m.generateBindsContent(binds) existingContent := ""
if data, err := os.ReadFile(overridePath); err == nil {
existingContent = string(data)
}
content := m.generatePreservedBindsContent(existingContent, binds, removed)
return os.WriteFile(overridePath, []byte(content), 0o644) return os.WriteFile(overridePath, []byte(content), 0o644)
} }
func (m *MangoWCProvider) generateBindsContent(binds map[string]*mangowcOverrideBind) string { func (m *MangoWCProvider) generatePreservedBindsContent(existingContent string, binds map[string]*mangowcOverrideBind, removed map[string]bool) string {
if len(binds) == 0 { useStockScaffold := m.shouldUseStockScaffold(existingContent)
return "" source := existingContent
if useStockScaffold {
source = m.stockBindsScaffold(binds)
} }
remaining := make(map[string]*mangowcOverrideBind, len(binds))
for key, bind := range binds {
remaining[key] = bind
}
if useStockScaffold {
m.dropReplacedStockBinds(remaining)
}
var lines []string
for _, line := range strings.Split(source, "\n") {
templateBind, ok := m.parseOverrideBindLine(line, m.previousComment(lines))
if !ok || templateBind == nil {
lines = append(lines, line)
continue
}
normalizedKey := strings.ToLower(templateBind.Key)
m.dropPreviousDescriptionComment(&lines)
if bind, exists := remaining[normalizedKey]; exists {
if useStockScaffold && bind.Description == "" {
bind = m.copyBindWithDescription(bind, templateBind.Description)
}
m.writeBindLineToLines(&lines, bind)
delete(remaining, normalizedKey)
continue
}
if useStockScaffold && !removed[normalizedKey] {
m.writeBindLineToLines(&lines, templateBind)
}
}
if len(remaining) > 0 {
m.trimTrailingEmptyLines(&lines)
if len(lines) > 0 {
lines = append(lines, "")
}
lines = append(lines, "# === Custom Keybinds ===")
for _, bind := range m.sortedBinds(remaining) {
m.writeBindLineToLines(&lines, bind)
}
}
m.trimTrailingEmptyLines(&lines)
if len(lines) == 0 {
return ""
}
return strings.Join(lines, "\n") + "\n"
}
func (m *MangoWCProvider) shouldUseStockScaffold(content string) bool {
if strings.TrimSpace(content) == "" {
return true
}
if strings.Contains(content, "gesturebind=") && strings.Contains(content, "# ===") {
return false
}
return !strings.Contains(content, "gesturebind=") && (strings.Count(content, "\nbind=")+strings.Count(content, "\nbindl=")+strings.Count(content, "\nbinds=")+strings.Count(content, "\nbindr=")+strings.Count(content, "\nbindp=") >= 10 || strings.Contains(content, "dms ipc call"))
}
func (m *MangoWCProvider) stockBindsScaffold(binds map[string]*mangowcOverrideBind) string {
terminalCommand := "ghostty"
for _, key := range []string{"super+t", "super+return"} {
if bind, ok := binds[key]; ok {
command, params := m.parseAction(bind.Action)
if command == "spawn" && strings.TrimSpace(params) != "" && !strings.Contains(params, "dms ") {
terminalCommand = params
break
}
}
}
return strings.ReplaceAll(config.MangoBindsConfig, "{{TERMINAL_COMMAND}}", terminalCommand)
}
func (m *MangoWCProvider) dropReplacedStockBinds(binds map[string]*mangowcOverrideBind) {
if bind, ok := binds["super+j"]; ok && bind.Action == "switch_layout" {
delete(binds, "super+j")
}
}
func (m *MangoWCProvider) sortedBinds(binds map[string]*mangowcOverrideBind) []*mangowcOverrideBind {
bindList := make([]*mangowcOverrideBind, 0, len(binds)) bindList := make([]*mangowcOverrideBind, 0, len(binds))
for _, bind := range binds { for _, bind := range binds {
bindList = append(bindList, bind) bindList = append(bindList, bind)
} }
sort.Slice(bindList, func(i, j int) bool { sort.Slice(bindList, func(i, j int) bool {
pi, pj := m.getBindSortPriority(bindList[i].Action), m.getBindSortPriority(bindList[j].Action) pi, pj := m.getBindSortPriority(bindList[i].Action), m.getBindSortPriority(bindList[j].Action)
if pi != pj { if pi != pj {
@@ -384,13 +536,55 @@ func (m *MangoWCProvider) generateBindsContent(binds map[string]*mangowcOverride
} }
return bindList[i].Key < bindList[j].Key return bindList[i].Key < bindList[j].Key
}) })
return bindList
var sb strings.Builder
for _, bind := range bindList {
m.writeBindLine(&sb, bind)
} }
return sb.String() func (m *MangoWCProvider) writeBindLineToLines(lines *[]string, bind *mangowcOverrideBind) {
var sb strings.Builder
m.writeBindLine(&sb, bind)
text := strings.TrimSuffix(sb.String(), "\n")
if text == "" {
return
}
*lines = append(*lines, strings.Split(text, "\n")...)
}
func (m *MangoWCProvider) previousComment(lines []string) string {
if len(lines) == 0 {
return ""
}
trimmed := strings.TrimSpace(lines[len(lines)-1])
if !strings.HasPrefix(trimmed, "#") {
return ""
}
comment := strings.TrimSpace(strings.TrimPrefix(trimmed, "#"))
if isMangoWCSectionComment(comment) {
return ""
}
return comment
}
func (m *MangoWCProvider) dropPreviousDescriptionComment(lines *[]string) {
if len(*lines) == 0 {
return
}
trimmed := strings.TrimSpace((*lines)[len(*lines)-1])
if !strings.HasPrefix(trimmed, "#") || strings.HasPrefix(trimmed, "# ===") {
return
}
*lines = (*lines)[:len(*lines)-1]
}
func (m *MangoWCProvider) trimTrailingEmptyLines(lines *[]string) {
for len(*lines) > 0 && strings.TrimSpace((*lines)[len(*lines)-1]) == "" {
*lines = (*lines)[:len(*lines)-1]
}
}
func (m *MangoWCProvider) copyBindWithDescription(bind *mangowcOverrideBind, description string) *mangowcOverrideBind {
copy := *bind
copy.Description = description
return &copy
} }
func (m *MangoWCProvider) writeBindLine(sb *strings.Builder, bind *mangowcOverrideBind) { func (m *MangoWCProvider) writeBindLine(sb *strings.Builder, bind *mangowcOverrideBind) {
@@ -405,7 +599,17 @@ func (m *MangoWCProvider) writeBindLine(sb *strings.Builder, bind *mangowcOverri
sb.WriteString("\n") sb.WriteString("\n")
} }
sb.WriteString("bind=") prefix := bind.Prefix
if prefix == "" {
prefix = "bind"
}
if prefix == mangowcAxisBindPrefix {
if direction, ok := mangowcScrollToDirection(key); ok {
key = direction
}
}
sb.WriteString(prefix)
sb.WriteString("=")
if mods == "" { if mods == "" {
sb.WriteString("none") sb.WriteString("none")
} else { } else {
@@ -424,6 +628,36 @@ func (m *MangoWCProvider) writeBindLine(sb *strings.Builder, bind *mangowcOverri
sb.WriteString("\n") sb.WriteString("\n")
} }
func (m *MangoWCProvider) bindPrefixFromOptions(options map[string]any) string {
if options == nil {
return ""
}
value, ok := options["flags"]
if !ok {
return ""
}
flags := ""
switch v := value.(type) {
case string:
flags = v
case fmt.Stringer:
flags = v.String()
default:
return ""
}
flags = strings.TrimSpace(flags)
if flags == "" {
return "bind"
}
var clean strings.Builder
for _, ch := range flags {
if strings.ContainsRune("lsrp", ch) && !strings.ContainsRune(clean.String(), ch) {
clean.WriteRune(ch)
}
}
return "bind" + clean.String()
}
func (m *MangoWCProvider) parseKeyString(keyStr string) (mods, key string) { func (m *MangoWCProvider) parseKeyString(keyStr string) (mods, key string) {
parts := strings.Split(keyStr, "+") parts := strings.Split(keyStr, "+")
switch len(parts) { switch len(parts) {
@@ -15,6 +15,10 @@ const (
var MangoWCModSeparators = []rune{'+', ' '} var MangoWCModSeparators = []rune{'+', ' '}
func isMangoWCSectionComment(comment string) bool {
return strings.HasPrefix(strings.TrimSpace(comment), "===")
}
type MangoWCKeyBinding struct { type MangoWCKeyBinding struct {
Mods []string `json:"mods"` Mods []string `json:"mods"`
Key string `json:"key"` Key string `json:"key"`
@@ -235,9 +239,12 @@ func (p *MangoWCParser) ParseKeys() []MangoWCKeyBinding {
} }
if strings.HasPrefix(trimmed, "#") { if strings.HasPrefix(trimmed, "#") {
pendingComment = strings.TrimSpace(strings.TrimPrefix(trimmed, "#")) pendingComment = strings.TrimSpace(strings.TrimPrefix(trimmed, "#"))
if isMangoWCSectionComment(pendingComment) {
pendingComment = ""
}
continue continue
} }
if !strings.HasPrefix(trimmed, "bind") { if !strings.HasPrefix(trimmed, "bind") && !strings.HasPrefix(trimmed, mangowcAxisBindPrefix) {
pendingComment = "" pendingComment = ""
continue continue
} }
@@ -414,10 +421,13 @@ func (p *MangoWCParser) parseFileWithSource(filePath string) ([]MangoWCKeyBindin
if strings.HasPrefix(trimmed, "#") { if strings.HasPrefix(trimmed, "#") {
pendingComment = strings.TrimSpace(strings.TrimPrefix(trimmed, "#")) pendingComment = strings.TrimSpace(strings.TrimPrefix(trimmed, "#"))
if isMangoWCSectionComment(pendingComment) {
pendingComment = ""
}
continue continue
} }
if !strings.HasPrefix(trimmed, "bind") { if !strings.HasPrefix(trimmed, "bind") && !strings.HasPrefix(trimmed, mangowcAxisBindPrefix) {
pendingComment = "" pendingComment = ""
continue continue
} }
@@ -483,7 +493,7 @@ func (p *MangoWCParser) parseDMSBindsDirectly(dmsBindsPath string) []MangoWCKeyB
// line directly above) is the description: mango feeds inline comments to spawn // line directly above) is the description: mango feeds inline comments to spawn
// as argv, so DMS keeps descriptions on the line above; inline `#` is a fallback. // as argv, so DMS keeps descriptions on the line above; inline `#` is a fallback.
func (p *MangoWCParser) getKeybindAtLineContent(line string, precedingComment string) *MangoWCKeyBinding { func (p *MangoWCParser) getKeybindAtLineContent(line string, precedingComment string) *MangoWCKeyBinding {
bindMatch := regexp.MustCompile(`^(bind[lsr]*)\s*=\s*(.+)$`) bindMatch := regexp.MustCompile(`^(bind[lsrp]*|axisbind)\s*=\s*(.+)$`)
matches := bindMatch.FindStringSubmatch(line) matches := bindMatch.FindStringSubmatch(line)
if len(matches) < 3 { if len(matches) < 3 {
return nil return nil
@@ -499,6 +509,9 @@ func (p *MangoWCParser) getKeybindAtLineContent(line string, precedingComment st
} }
if comment == "" { if comment == "" {
comment = strings.TrimSpace(precedingComment) comment = strings.TrimSpace(precedingComment)
if isMangoWCSectionComment(comment) {
comment = ""
}
} }
if strings.HasPrefix(comment, MangoWCHideComment) { if strings.HasPrefix(comment, MangoWCHideComment) {
@@ -514,6 +527,12 @@ func (p *MangoWCParser) getKeybindAtLineContent(line string, precedingComment st
key := strings.TrimSpace(keyFields[1]) key := strings.TrimSpace(keyFields[1])
command := strings.TrimSpace(keyFields[2]) command := strings.TrimSpace(keyFields[2])
if matches[1] == mangowcAxisBindPrefix {
if canonical, ok := mangowcDirectionToScroll(key); ok {
key = canonical
}
}
var params string var params string
if len(keyFields) > 3 { if len(keyFields) > 3 {
params = strings.TrimSpace(keyFields[3]) params = strings.TrimSpace(keyFields[3])
@@ -6,6 +6,29 @@ import (
"testing" "testing"
) )
func TestMangoWCParseAxisBindToScrollKey(t *testing.T) {
tmpDir := t.TempDir()
cfg := filepath.Join(tmpDir, "config.conf")
content := "axisbind=SUPER,UP,spawn,dms ipc call test\n"
if err := os.WriteFile(cfg, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
binds, err := ParseMangoWCKeys(cfg)
if err != nil {
t.Fatalf("ParseMangoWCKeys failed: %v", err)
}
if len(binds) != 1 {
t.Fatalf("expected 1 bind, got %d", len(binds))
}
if binds[0].Key != "WheelScrollUp" {
t.Fatalf("expected axis direction parsed as WheelScrollUp, got %q", binds[0].Key)
}
if len(binds[0].Mods) != 1 || binds[0].Mods[0] != "SUPER" {
t.Fatalf("expected SUPER mod, got %v", binds[0].Mods)
}
}
func TestMangoWCAutogenerateComment(t *testing.T) { func TestMangoWCAutogenerateComment(t *testing.T) {
tests := []struct { tests := []struct {
command string command string
@@ -73,6 +96,7 @@ func TestMangoWCGetKeybindAtLine(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
line string line string
precedingComment string
expected *MangoWCKeyBinding expected *MangoWCKeyBinding
}{ }{
{ {
@@ -157,6 +181,41 @@ func TestMangoWCGetKeybindAtLine(t *testing.T) {
Comment: "dms ipc call lock lock", Comment: "dms ipc call lock lock",
}, },
}, },
{
name: "bindp_flag",
line: "bindp=SUPER,p,spawn,pass-through",
expected: &MangoWCKeyBinding{
Mods: []string{"SUPER"},
Key: "p",
Command: "spawn",
Params: "pass-through",
Comment: "pass-through",
},
},
{
name: "preceding_comment",
line: "bind=SUPER+SHIFT,S,spawn,dms screenshot",
precedingComment: "Screenshot: Interactive",
expected: &MangoWCKeyBinding{
Mods: []string{"SUPER", "SHIFT"},
Key: "S",
Command: "spawn",
Params: "dms screenshot",
Comment: "Screenshot: Interactive",
},
},
{
name: "section_header_not_description",
line: "bind=none,XF86AudioRaiseVolume,spawn,dms ipc call audio increment 3",
precedingComment: "=== Audio Controls ===",
expected: &MangoWCKeyBinding{
Mods: []string{},
Key: "XF86AudioRaiseVolume",
Command: "spawn",
Params: "dms ipc call audio increment 3",
Comment: "dms ipc call audio increment 3",
},
},
{ {
name: "keybind_with_spaces", name: "keybind_with_spaces",
line: "bind = SUPER, r, reload_config", line: "bind = SUPER, r, reload_config",
@@ -174,7 +233,7 @@ func TestMangoWCGetKeybindAtLine(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
parser := NewMangoWCParser("") parser := NewMangoWCParser("")
parser.contentLines = []string{tt.line} parser.contentLines = []string{tt.line}
result := parser.getKeybindAtLine(0, "") result := parser.getKeybindAtLine(0, tt.precedingComment)
if tt.expected == nil { if tt.expected == nil {
if result != nil { if result != nil {
@@ -3,7 +3,10 @@ package providers
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"strings"
"testing" "testing"
"github.com/AvengeMedia/DankMaterialShell/core/internal/config"
) )
func TestMangoWCProviderName(t *testing.T) { func TestMangoWCProviderName(t *testing.T) {
@@ -318,3 +321,172 @@ bind=Ctrl,1,view,1,0
t.Error("Did not find terminal keybind with correct key and description") t.Error("Did not find terminal keybind with correct key and description")
} }
} }
func TestMangoWCSetBindPreservesStockCommentsAndGestures(t *testing.T) {
tmpDir := t.TempDir()
dmsDir := filepath.Join(tmpDir, "dms")
if err := os.MkdirAll(dmsDir, 0o755); err != nil {
t.Fatalf("failed to create dms dir: %v", err)
}
bindsPath := filepath.Join(dmsDir, "binds.conf")
stock := strings.ReplaceAll(config.MangoBindsConfig, "{{TERMINAL_COMMAND}}", "ghostty")
if err := os.WriteFile(bindsPath, []byte(stock), 0o644); err != nil {
t.Fatalf("failed to write stock binds: %v", err)
}
provider := NewMangoWCProvider(tmpDir)
if err := provider.SetBind("SUPER+SHIFT+S", "spawn dms screenshot", "Screenshot: Interactive", nil); err != nil {
t.Fatalf("SetBind failed: %v", err)
}
contentBytes, err := os.ReadFile(bindsPath)
if err != nil {
t.Fatalf("failed to read binds: %v", err)
}
content := string(contentBytes)
for _, want := range []string{
"# === Application Launchers ===",
"# === Touchpad Gestures ===",
"gesturebind=none,right,3,viewtoleft_have_client",
"gesturebind=none,left,3,viewtoright_have_client",
"# Screenshot: Interactive\nbind=SUPER+SHIFT,S,spawn,dms screenshot",
} {
if !strings.Contains(content, want) {
t.Fatalf("expected saved binds to contain %q\ncontent:\n%s", want, content)
}
}
if strings.Contains(content, "# === Audio Controls ===\n# === Audio Controls ===") {
t.Fatalf("section header should not be duplicated as a bind description\ncontent:\n%s", content)
}
}
func TestMangoWCSetBindRestoresScaffoldForStrippedFile(t *testing.T) {
tmpDir := t.TempDir()
dmsDir := filepath.Join(tmpDir, "dms")
if err := os.MkdirAll(dmsDir, 0o755); err != nil {
t.Fatalf("failed to create dms dir: %v", err)
}
bindsPath := filepath.Join(dmsDir, "binds.conf")
stripped := `bind=SUPER,t,spawn,ghostty
bind=SUPER,Return,spawn,ghostty
bind=SUPER,space,spawn,dms ipc call spotlight toggle
bind=SUPER,v,spawn,dms ipc call clipboard toggle
bind=SUPER,q,killclient
bind=SUPER,Left,focusdir,left
bind=SUPER,Right,focusdir,right
bind=SUPER,Up,focusdir,up
bind=SUPER,Down,focusdir,down
bind=SUPER,1,view,1
bind=SUPER,2,view,2
bind=SUPER,3,view,3
`
if err := os.WriteFile(bindsPath, []byte(stripped), 0o644); err != nil {
t.Fatalf("failed to write stripped binds: %v", err)
}
provider := NewMangoWCProvider(tmpDir)
if err := provider.SetBind("SUPER+SHIFT+S", "spawn dms screenshot", "Screenshot: Interactive", nil); err != nil {
t.Fatalf("SetBind failed: %v", err)
}
contentBytes, err := os.ReadFile(bindsPath)
if err != nil {
t.Fatalf("failed to read binds: %v", err)
}
content := string(contentBytes)
for _, want := range []string{
"# DMS default keybinds (MangoWM)",
"# === Touchpad Gestures ===",
"gesturebind=none,right,3,viewtoleft_have_client",
"bind=SUPER,H,focusdir,left",
"bind=SUPER,J,focusdir,down",
"bind=SUPER,K,focusdir,up",
"bind=SUPER,L,focusdir,right",
"# === Custom Keybinds ===",
"# Screenshot: Interactive\nbind=SUPER+SHIFT,S,spawn,dms screenshot",
"bind=SUPER,t,spawn,ghostty",
} {
if !strings.Contains(content, want) {
t.Fatalf("expected restored binds to contain %q\ncontent:\n%s", want, content)
}
}
if strings.Contains(content, "{{TERMINAL_COMMAND}}") {
t.Fatalf("terminal placeholder should have been resolved\ncontent:\n%s", content)
}
}
func TestMangoWCSetBindTranslatesScrollWheelToAxisBind(t *testing.T) {
tmpDir := t.TempDir()
dmsDir := filepath.Join(tmpDir, "dms")
if err := os.MkdirAll(dmsDir, 0o755); err != nil {
t.Fatalf("failed to create dms dir: %v", err)
}
bindsPath := filepath.Join(dmsDir, "binds.conf")
seed := "# === Custom Keybinds ===\nbind=SUPER,t,spawn,ghostty\ngesturebind=none,left,3,focusdir,left\n"
if err := os.WriteFile(bindsPath, []byte(seed), 0o644); err != nil {
t.Fatalf("failed to write seed binds: %v", err)
}
provider := NewMangoWCProvider(tmpDir)
if err := provider.SetBind("SUPER+WheelScrollDown", "spawn dms ipc call test", "Scroll down", nil); err != nil {
t.Fatalf("SetBind failed: %v", err)
}
content := readFile(t, bindsPath)
if !strings.Contains(content, "axisbind=SUPER,DOWN,spawn,dms ipc call test") {
t.Fatalf("expected scroll bind written as axisbind direction, got:\n%s", content)
}
if strings.Contains(content, "WheelScroll") {
t.Fatalf("expected no raw niri scroll keysym in mango output, got:\n%s", content)
}
if err := provider.SetBind("SUPER+WheelScrollDown", "spawn dms ipc call test2", "Scroll down", nil); err != nil {
t.Fatalf("SetBind failed: %v", err)
}
content = readFile(t, bindsPath)
if strings.Count(content, "axisbind=SUPER,DOWN,") != 1 {
t.Fatalf("expected exactly one axisbind after re-save, got:\n%s", content)
}
}
func TestMangoWCRemoveBindPreservesNonBindLines(t *testing.T) {
tmpDir := t.TempDir()
dmsDir := filepath.Join(tmpDir, "dms")
if err := os.MkdirAll(dmsDir, 0o755); err != nil {
t.Fatalf("failed to create dms dir: %v", err)
}
bindsPath := filepath.Join(dmsDir, "binds.conf")
stock := strings.ReplaceAll(config.MangoBindsConfig, "{{TERMINAL_COMMAND}}", "ghostty")
if err := os.WriteFile(bindsPath, []byte(stock), 0o644); err != nil {
t.Fatalf("failed to write stock binds: %v", err)
}
provider := NewMangoWCProvider(tmpDir)
if err := provider.RemoveBind("SUPER+Tab"); err != nil {
t.Fatalf("RemoveBind failed: %v", err)
}
contentBytes, err := os.ReadFile(bindsPath)
if err != nil {
t.Fatalf("failed to read binds: %v", err)
}
content := string(contentBytes)
if strings.Contains(content, "bind=SUPER,Tab,focusstack,next") {
t.Fatalf("removed bind should be absent\ncontent:\n%s", content)
}
if strings.Contains(content, "# Focus Next Window") {
t.Fatalf("removed bind description should be absent\ncontent:\n%s", content)
}
for _, want := range []string{
"# === Focus Navigation ===",
"# === Touchpad Gestures ===",
"gesturebind=none,down,4,toggleoverview",
} {
if !strings.Contains(content, want) {
t.Fatalf("expected non-bind line %q to be preserved\ncontent:\n%s", want, content)
}
}
}
@@ -51,7 +51,7 @@ type NiriParser struct {
} }
func parseKDL(data []byte) (*document.Document, error) { func parseKDL(data []byte) (*document.Document, error) {
return kdl.Parse(strings.NewReader(normalizeKDLBraces(string(data)))) return kdl.Parse(strings.NewReader(normalizeKDLBraces(quoteLeadingUnderscoreIdents(string(data)))))
} }
func normalizeKDLBraces(input string) string { func normalizeKDLBraces(input string) string {
@@ -94,6 +94,93 @@ func normalizeKDLBraces(input string) string {
return sb.String() return sb.String()
} }
// quoteLeadingUnderscoreIdents wraps bare KDL identifiers that begin with '_'
// in double quotes. kdl-go rejects '_' as the first character of a bare
// identifier (e.g. the common `_JAVA_AWT_WM_NONREPARENTING "1"` environment
// node), even though niri's own parser and the KDL spec accept it — so without
// this the whole config fails to parse and no keybinds load. Quoting lets
// kdl-go parse it; this is safe because the niri parser only dispatches on
// fixed node/section names (binds, recent-windows, include, ...) that never
// start with '_', so re-quoting such a name cannot change what DMS reads.
// Underscores elsewhere in an identifier (XDG_CURRENT_DESKTOP) are left
// untouched, and underscores inside strings or comments are skipped. Only a
// leading '_' is handled; other start characters kdl-go over-rejects (e.g. '.'
// or '?') do not occur in niri configs.
func quoteLeadingUnderscoreIdents(input string) string {
var sb strings.Builder
sb.Grow(len(input))
var prev byte
n := len(input)
for i := 0; i < n; {
c := input[i]
switch {
case c == '"':
end := findStringEnd(input, i)
sb.WriteString(input[i:end])
prev = '"'
i = end
case c == '/' && i+1 < n && input[i+1] == '/':
end := findLineCommentEnd(input, i)
sb.WriteString(input[i:end])
prev = '\n'
i = end
case c == '/' && i+1 < n && input[i+1] == '*':
end := findBlockCommentEnd(input, i)
sb.WriteString(input[i:end])
prev = ' '
i = end
case c == '/' && i+1 < n && input[i+1] == '-':
// KDL slashdash: /- comments out the next node/value. Keep the
// marker but treat what follows as a fresh token start, so a
// slashdashed leading-underscore node (e.g. `/-_FOO "1"`) still
// gets quoted instead of crashing kdl-go.
sb.WriteByte('/')
sb.WriteByte('-')
prev = ' '
i += 2
case c == '_' && isIdentBoundary(prev):
end := scanBareIdent(input, i)
sb.WriteByte('"')
sb.WriteString(input[i:end])
sb.WriteByte('"')
prev = '"'
i = end
default:
sb.WriteByte(c)
prev = c
i++
}
}
return sb.String()
}
// isIdentBoundary reports whether the previously emitted byte ends a token, so
// that a following '_' starts a fresh bare identifier rather than sitting in
// the middle of one.
func isIdentBoundary(prev byte) bool {
switch prev {
case 0, ' ', '\t', '\n', '\r', '{', '}', ';', '=', '(', ')', ',':
return true
}
return false
}
// scanBareIdent returns the index just past the bare identifier starting at
// start, stopping at whitespace or any KDL delimiter.
func scanBareIdent(s string, start int) int {
n := len(s)
for i := start; i < n; i++ {
switch s[i] {
case ' ', '\t', '\n', '\r', '"', '{', '}', '(', ')', ';', '=', ',', '/', '\\', '<', '>', '[', ']':
return i
}
}
return n
}
func findStringEnd(s string, start int) int { func findStringEnd(s string, start int) int {
n := len(s) n := len(s)
for i := start + 1; i < n; { for i := start + 1; i < n; {
@@ -71,6 +71,101 @@ func TestNormalizeKDLBraces(t *testing.T) {
} }
} }
func TestQuoteLeadingUnderscoreIdents(t *testing.T) {
tests := []struct {
name string
in string
out string
}{
{"leading underscore node", `_JAVA_AWT_WM_NONREPARENTING "1"`, `"_JAVA_AWT_WM_NONREPARENTING" "1"`},
{"mid underscore untouched", `XDG_CURRENT_DESKTOP "niri"`, `XDG_CURRENT_DESKTOP "niri"`},
{"indented node", "environment {\n _FOO \"1\"\n}", "environment {\n \"_FOO\" \"1\"\n}"},
{"underscore in string", `spawn "_not_a_node"`, `spawn "_not_a_node"`},
{"underscore in line comment", "// _comment\n_FOO \"1\"", "// _comment\n\"_FOO\" \"1\""},
{"underscore in block comment", "/* _x */ _FOO \"1\"", "/* _x */ \"_FOO\" \"1\""},
{"block comment abuts node", `/* x */_FOO "1"`, `/* x */"_FOO" "1"`},
{"slashdash before node", `/-_FOO "1"`, `/-"_FOO" "1"`},
{"node after closing paren", "node (u8)_v", `node (u8)"_v"`},
{"node before brace without space", "_FOO{ }", `"_FOO"{ }`},
{"lone underscore", `_ "x"`, `"_" "x"`},
{"property value", "node key=_val", `node key="_val"`},
{"no underscores", "node child", "node child"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := quoteLeadingUnderscoreIdents(tc.in)
if got != tc.out {
t.Errorf("quoteLeadingUnderscoreIdents(%q) = %q, want %q", tc.in, got, tc.out)
}
})
}
}
func TestNiriParseLeadingUnderscoreEnvironment(t *testing.T) {
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.kdl")
// A leading-underscore environment node (a common Java/tiling-WM fix) must
// not abort parsing of the rest of the config — keybinds still have to load.
content := `environment {
XDG_CURRENT_DESKTOP "niri"
_JAVA_AWT_WM_NONREPARENTING "1"
}
binds {
Mod+Q { close-window; }
Mod+KP_Home { focus-workspace 1; }
}
`
if err := os.WriteFile(configFile, []byte(content), 0o644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
result, err := ParseNiriKeys(tmpDir)
if err != nil {
t.Fatalf("ParseNiriKeys failed on config with leading-underscore env node: %v", err)
}
if len(result.Section.Keybinds) != 2 {
t.Errorf("Expected 2 keybinds, got %d", len(result.Section.Keybinds))
}
foundClose := false
for _, kb := range result.Section.Keybinds {
if kb.Action == "close-window" {
foundClose = true
}
}
if !foundClose {
t.Error("close-window keybind not found — leading-underscore env node broke parsing")
}
}
func TestNiriParseSlashdashLeadingUnderscore(t *testing.T) {
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.kdl")
// A slashdashed leading-underscore node must not abort parsing either.
content := `environment {
/-_JAVA_AWT_WM_NONREPARENTING "1"
}
binds {
Mod+Q { close-window; }
}
`
if err := os.WriteFile(configFile, []byte(content), 0o644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
result, err := ParseNiriKeys(tmpDir)
if err != nil {
t.Fatalf("ParseNiriKeys failed on config with slashdashed leading-underscore node: %v", err)
}
if len(result.Section.Keybinds) != 1 {
t.Errorf("Expected 1 keybind, got %d", len(result.Section.Keybinds))
}
}
func TestNiriParseKeyCombo(t *testing.T) { func TestNiriParseKeyCombo(t *testing.T) {
tests := []struct { tests := []struct {
combo string combo string
@@ -0,0 +1,74 @@
package providers
import "strings"
// Scroll-wheel binds are captured by the shell as niri's keysym names
// (WheelScrollUp/Down/Left/Right) regardless of the active compositor. Niri
// consumes them natively; every other provider speaks a different dialect, so the
// raw niri token must be translated on write and back again on read. Without this
// the token is emitted verbatim and the compositor rejects the bind (issue #2683).
var canonicalScrollKeys = map[string]string{
"wheelscrollup": "WheelScrollUp",
"wheelscrolldown": "WheelScrollDown",
"wheelscrollleft": "WheelScrollLeft",
"wheelscrollright": "WheelScrollRight",
}
func isScrollKey(token string) bool {
_, ok := canonicalScrollKeys[strings.ToLower(token)]
return ok
}
// Hyprland binds the wheel inside a regular bind using mouse_up/down/left/right.
var hyprlandScrollNative = map[string]string{
"wheelscrollup": "mouse_up",
"wheelscrolldown": "mouse_down",
"wheelscrollleft": "mouse_left",
"wheelscrollright": "mouse_right",
}
var hyprlandScrollCanonical = map[string]string{
"mouse_up": "WheelScrollUp",
"mouse_down": "WheelScrollDown",
"mouse_left": "WheelScrollLeft",
"mouse_right": "WheelScrollRight",
}
func hyprlandScrollToNative(token string) (string, bool) {
v, ok := hyprlandScrollNative[strings.ToLower(token)]
return v, ok
}
func hyprlandScrollToCanonical(token string) (string, bool) {
v, ok := hyprlandScrollCanonical[strings.ToLower(token)]
return v, ok
}
// MangoWC binds the wheel through a dedicated axisbind directive whose key field
// is a direction (UP/DOWN/LEFT/RIGHT) rather than a keysym.
const mangowcAxisBindPrefix = "axisbind"
var mangowcScrollDirection = map[string]string{
"wheelscrollup": "UP",
"wheelscrolldown": "DOWN",
"wheelscrollleft": "LEFT",
"wheelscrollright": "RIGHT",
}
var mangowcScrollCanonical = map[string]string{
"up": "WheelScrollUp",
"down": "WheelScrollDown",
"left": "WheelScrollLeft",
"right": "WheelScrollRight",
}
func mangowcScrollToDirection(token string) (string, bool) {
v, ok := mangowcScrollDirection[strings.ToLower(token)]
return v, ok
}
func mangowcDirectionToScroll(direction string) (string, bool) {
v, ok := mangowcScrollCanonical[strings.ToLower(direction)]
return v, ok
}
+45 -35
View File
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_brightness package mocks_brightness
import ( import (
dbus "github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockDBusConn creates a new instance of MockDBusConn. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockDBusConn(t interface {
mock.TestingT
Cleanup(func())
}) *MockDBusConn {
mock := &MockDBusConn{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockDBusConn is an autogenerated mock type for the DBusConn type // MockDBusConn is an autogenerated mock type for the DBusConn type
type MockDBusConn struct { type MockDBusConn struct {
mock.Mock mock.Mock
@@ -20,21 +36,20 @@ func (_m *MockDBusConn) EXPECT() *MockDBusConn_Expecter {
return &MockDBusConn_Expecter{mock: &_m.Mock} return &MockDBusConn_Expecter{mock: &_m.Mock}
} }
// Close provides a mock function with no fields // Close provides a mock function for the type MockDBusConn
func (_m *MockDBusConn) Close() error { func (_mock *MockDBusConn) Close() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Close") panic("no return value specified for Close")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -55,8 +70,8 @@ func (_c *MockDBusConn_Close_Call) Run(run func()) *MockDBusConn_Close_Call {
return _c return _c
} }
func (_c *MockDBusConn_Close_Call) Return(_a0 error) *MockDBusConn_Close_Call { func (_c *MockDBusConn_Close_Call) Return(err error) *MockDBusConn_Close_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -65,23 +80,22 @@ func (_c *MockDBusConn_Close_Call) RunAndReturn(run func() error) *MockDBusConn_
return _c return _c
} }
// Object provides a mock function with given fields: dest, path // Object provides a mock function for the type MockDBusConn
func (_m *MockDBusConn) Object(dest string, path dbus.ObjectPath) dbus.BusObject { func (_mock *MockDBusConn) Object(dest string, path dbus.ObjectPath) dbus.BusObject {
ret := _m.Called(dest, path) ret := _mock.Called(dest, path)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Object") panic("no return value specified for Object")
} }
var r0 dbus.BusObject var r0 dbus.BusObject
if rf, ok := ret.Get(0).(func(string, dbus.ObjectPath) dbus.BusObject); ok { if returnFunc, ok := ret.Get(0).(func(string, dbus.ObjectPath) dbus.BusObject); ok {
r0 = rf(dest, path) r0 = returnFunc(dest, path)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(dbus.BusObject) r0 = ret.Get(0).(dbus.BusObject)
} }
} }
return r0 return r0
} }
@@ -99,32 +113,28 @@ func (_e *MockDBusConn_Expecter) Object(dest any, path any) *MockDBusConn_Object
func (_c *MockDBusConn_Object_Call) Run(run func(dest string, path dbus.ObjectPath)) *MockDBusConn_Object_Call { func (_c *MockDBusConn_Object_Call) Run(run func(dest string, path dbus.ObjectPath)) *MockDBusConn_Object_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string), args[1].(dbus.ObjectPath)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 dbus.ObjectPath
if args[1] != nil {
arg1 = args[1].(dbus.ObjectPath)
}
run(
arg0,
arg1,
)
}) })
return _c return _c
} }
func (_c *MockDBusConn_Object_Call) Return(_a0 dbus.BusObject) *MockDBusConn_Object_Call { func (_c *MockDBusConn_Object_Call) Return(busObject dbus.BusObject) *MockDBusConn_Object_Call {
_c.Call.Return(_a0) _c.Call.Return(busObject)
return _c return _c
} }
func (_c *MockDBusConn_Object_Call) RunAndReturn(run func(string, dbus.ObjectPath) dbus.BusObject) *MockDBusConn_Object_Call { func (_c *MockDBusConn_Object_Call) RunAndReturn(run func(dest string, path dbus.ObjectPath) dbus.BusObject) *MockDBusConn_Object_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockDBusConn creates a new instance of MockDBusConn. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockDBusConn(t interface {
mock.TestingT
Cleanup(func())
},
) *MockDBusConn {
mock := &MockDBusConn{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+81 -81
View File
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_evdev package mocks_evdev
import ( import (
go_evdev "github.com/holoplot/go-evdev" "github.com/holoplot/go-evdev"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockEvdevDevice creates a new instance of MockEvdevDevice. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockEvdevDevice(t interface {
mock.TestingT
Cleanup(func())
}) *MockEvdevDevice {
mock := &MockEvdevDevice{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockEvdevDevice is an autogenerated mock type for the EvdevDevice type // MockEvdevDevice is an autogenerated mock type for the EvdevDevice type
type MockEvdevDevice struct { type MockEvdevDevice struct {
mock.Mock mock.Mock
@@ -20,21 +36,20 @@ func (_m *MockEvdevDevice) EXPECT() *MockEvdevDevice_Expecter {
return &MockEvdevDevice_Expecter{mock: &_m.Mock} return &MockEvdevDevice_Expecter{mock: &_m.Mock}
} }
// Close provides a mock function with no fields // Close provides a mock function for the type MockEvdevDevice
func (_m *MockEvdevDevice) Close() error { func (_mock *MockEvdevDevice) Close() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Close") panic("no return value specified for Close")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -55,8 +70,8 @@ func (_c *MockEvdevDevice_Close_Call) Run(run func()) *MockEvdevDevice_Close_Cal
return _c return _c
} }
func (_c *MockEvdevDevice_Close_Call) Return(_a0 error) *MockEvdevDevice_Close_Call { func (_c *MockEvdevDevice_Close_Call) Return(err error) *MockEvdevDevice_Close_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -65,9 +80,9 @@ func (_c *MockEvdevDevice_Close_Call) RunAndReturn(run func() error) *MockEvdevD
return _c return _c
} }
// Name provides a mock function with no fields // Name provides a mock function for the type MockEvdevDevice
func (_m *MockEvdevDevice) Name() (string, error) { func (_mock *MockEvdevDevice) Name() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Name") panic("no return value specified for Name")
@@ -75,21 +90,19 @@ func (_m *MockEvdevDevice) Name() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -110,8 +123,8 @@ func (_c *MockEvdevDevice_Name_Call) Run(run func()) *MockEvdevDevice_Name_Call
return _c return _c
} }
func (_c *MockEvdevDevice_Name_Call) Return(_a0 string, _a1 error) *MockEvdevDevice_Name_Call { func (_c *MockEvdevDevice_Name_Call) Return(s string, err error) *MockEvdevDevice_Name_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -120,21 +133,20 @@ func (_c *MockEvdevDevice_Name_Call) RunAndReturn(run func() (string, error)) *M
return _c return _c
} }
// Path provides a mock function with no fields // Path provides a mock function for the type MockEvdevDevice
func (_m *MockEvdevDevice) Path() string { func (_mock *MockEvdevDevice) Path() string {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Path") panic("no return value specified for Path")
} }
var r0 string var r0 string
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
return r0 return r0
} }
@@ -155,8 +167,8 @@ func (_c *MockEvdevDevice_Path_Call) Run(run func()) *MockEvdevDevice_Path_Call
return _c return _c
} }
func (_c *MockEvdevDevice_Path_Call) Return(_a0 string) *MockEvdevDevice_Path_Call { func (_c *MockEvdevDevice_Path_Call) Return(s string) *MockEvdevDevice_Path_Call {
_c.Call.Return(_a0) _c.Call.Return(s)
return _c return _c
} }
@@ -165,33 +177,31 @@ func (_c *MockEvdevDevice_Path_Call) RunAndReturn(run func() string) *MockEvdevD
return _c return _c
} }
// ReadOne provides a mock function with no fields // ReadOne provides a mock function for the type MockEvdevDevice
func (_m *MockEvdevDevice) ReadOne() (*go_evdev.InputEvent, error) { func (_mock *MockEvdevDevice) ReadOne() (*evdev.InputEvent, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for ReadOne") panic("no return value specified for ReadOne")
} }
var r0 *go_evdev.InputEvent var r0 *evdev.InputEvent
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (*go_evdev.InputEvent, error)); ok { if returnFunc, ok := ret.Get(0).(func() (*evdev.InputEvent, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() *go_evdev.InputEvent); ok { if returnFunc, ok := ret.Get(0).(func() *evdev.InputEvent); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*go_evdev.InputEvent) r0 = ret.Get(0).(*evdev.InputEvent)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -212,43 +222,41 @@ func (_c *MockEvdevDevice_ReadOne_Call) Run(run func()) *MockEvdevDevice_ReadOne
return _c return _c
} }
func (_c *MockEvdevDevice_ReadOne_Call) Return(_a0 *go_evdev.InputEvent, _a1 error) *MockEvdevDevice_ReadOne_Call { func (_c *MockEvdevDevice_ReadOne_Call) Return(inputEvent *evdev.InputEvent, err error) *MockEvdevDevice_ReadOne_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(inputEvent, err)
return _c return _c
} }
func (_c *MockEvdevDevice_ReadOne_Call) RunAndReturn(run func() (*go_evdev.InputEvent, error)) *MockEvdevDevice_ReadOne_Call { func (_c *MockEvdevDevice_ReadOne_Call) RunAndReturn(run func() (*evdev.InputEvent, error)) *MockEvdevDevice_ReadOne_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// State provides a mock function with given fields: t // State provides a mock function for the type MockEvdevDevice
func (_m *MockEvdevDevice) State(t go_evdev.EvType) (go_evdev.StateMap, error) { func (_mock *MockEvdevDevice) State(t evdev.EvType) (evdev.StateMap, error) {
ret := _m.Called(t) ret := _mock.Called(t)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for State") panic("no return value specified for State")
} }
var r0 go_evdev.StateMap var r0 evdev.StateMap
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(go_evdev.EvType) (go_evdev.StateMap, error)); ok { if returnFunc, ok := ret.Get(0).(func(evdev.EvType) (evdev.StateMap, error)); ok {
return rf(t) return returnFunc(t)
} }
if rf, ok := ret.Get(0).(func(go_evdev.EvType) go_evdev.StateMap); ok { if returnFunc, ok := ret.Get(0).(func(evdev.EvType) evdev.StateMap); ok {
r0 = rf(t) r0 = returnFunc(t)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(go_evdev.StateMap) r0 = ret.Get(0).(evdev.StateMap)
} }
} }
if returnFunc, ok := ret.Get(1).(func(evdev.EvType) error); ok {
if rf, ok := ret.Get(1).(func(go_evdev.EvType) error); ok { r1 = returnFunc(t)
r1 = rf(t)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -258,38 +266,30 @@ type MockEvdevDevice_State_Call struct {
} }
// State is a helper method to define mock.On call // State is a helper method to define mock.On call
// - t go_evdev.EvType // - t evdev.EvType
func (_e *MockEvdevDevice_Expecter) State(t interface{}) *MockEvdevDevice_State_Call { func (_e *MockEvdevDevice_Expecter) State(t any) *MockEvdevDevice_State_Call {
return &MockEvdevDevice_State_Call{Call: _e.mock.On("State", t)} return &MockEvdevDevice_State_Call{Call: _e.mock.On("State", t)}
} }
func (_c *MockEvdevDevice_State_Call) Run(run func(t go_evdev.EvType)) *MockEvdevDevice_State_Call { func (_c *MockEvdevDevice_State_Call) Run(run func(t evdev.EvType)) *MockEvdevDevice_State_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(go_evdev.EvType)) var arg0 evdev.EvType
if args[0] != nil {
arg0 = args[0].(evdev.EvType)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockEvdevDevice_State_Call) Return(_a0 go_evdev.StateMap, _a1 error) *MockEvdevDevice_State_Call { func (_c *MockEvdevDevice_State_Call) Return(stateMap evdev.StateMap, err error) *MockEvdevDevice_State_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(stateMap, err)
return _c return _c
} }
func (_c *MockEvdevDevice_State_Call) RunAndReturn(run func(go_evdev.EvType) (go_evdev.StateMap, error)) *MockEvdevDevice_State_Call { func (_c *MockEvdevDevice_State_Call) RunAndReturn(run func(t evdev.EvType) (evdev.StateMap, error)) *MockEvdevDevice_State_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockEvdevDevice creates a new instance of MockEvdevDevice. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockEvdevDevice(t interface {
mock.TestingT
Cleanup(func())
}) *MockEvdevDevice {
mock := &MockEvdevDevice{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
+62 -49
View File
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_geolocation package mocks_geolocation
import ( import (
geolocation "github.com/AvengeMedia/DankMaterialShell/core/internal/geolocation" "github.com/AvengeMedia/DankMaterialShell/core/internal/geolocation"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockClient creates a new instance of MockClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockClient(t interface {
mock.TestingT
Cleanup(func())
}) *MockClient {
mock := &MockClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockClient is an autogenerated mock type for the Client type // MockClient is an autogenerated mock type for the Client type
type MockClient struct { type MockClient struct {
mock.Mock mock.Mock
@@ -20,9 +36,10 @@ func (_m *MockClient) EXPECT() *MockClient_Expecter {
return &MockClient_Expecter{mock: &_m.Mock} return &MockClient_Expecter{mock: &_m.Mock}
} }
// Close provides a mock function with no fields // Close provides a mock function for the type MockClient
func (_m *MockClient) Close() { func (_mock *MockClient) Close() {
_m.Called() _mock.Called()
return
} }
// MockClient_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' // MockClient_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
@@ -52,9 +69,9 @@ func (_c *MockClient_Close_Call) RunAndReturn(run func()) *MockClient_Close_Call
return _c return _c
} }
// GetLocation provides a mock function with no fields // GetLocation provides a mock function for the type MockClient
func (_m *MockClient) GetLocation() (geolocation.Location, error) { func (_mock *MockClient) GetLocation() (geolocation.Location, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetLocation") panic("no return value specified for GetLocation")
@@ -62,21 +79,19 @@ func (_m *MockClient) GetLocation() (geolocation.Location, error) {
var r0 geolocation.Location var r0 geolocation.Location
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (geolocation.Location, error)); ok { if returnFunc, ok := ret.Get(0).(func() (geolocation.Location, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() geolocation.Location); ok { if returnFunc, ok := ret.Get(0).(func() geolocation.Location); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(geolocation.Location) r0 = ret.Get(0).(geolocation.Location)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -97,8 +112,8 @@ func (_c *MockClient_GetLocation_Call) Run(run func()) *MockClient_GetLocation_C
return _c return _c
} }
func (_c *MockClient_GetLocation_Call) Return(_a0 geolocation.Location, _a1 error) *MockClient_GetLocation_Call { func (_c *MockClient_GetLocation_Call) Return(location geolocation.Location, err error) *MockClient_GetLocation_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(location, err)
return _c return _c
} }
@@ -107,23 +122,22 @@ func (_c *MockClient_GetLocation_Call) RunAndReturn(run func() (geolocation.Loca
return _c return _c
} }
// Subscribe provides a mock function with given fields: id // Subscribe provides a mock function for the type MockClient
func (_m *MockClient) Subscribe(id string) chan geolocation.Location { func (_mock *MockClient) Subscribe(id string) chan geolocation.Location {
ret := _m.Called(id) ret := _mock.Called(id)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Subscribe") panic("no return value specified for Subscribe")
} }
var r0 chan geolocation.Location var r0 chan geolocation.Location
if rf, ok := ret.Get(0).(func(string) chan geolocation.Location); ok { if returnFunc, ok := ret.Get(0).(func(string) chan geolocation.Location); ok {
r0 = rf(id) r0 = returnFunc(id)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(chan geolocation.Location) r0 = ret.Get(0).(chan geolocation.Location)
} }
} }
return r0 return r0
} }
@@ -134,30 +148,37 @@ type MockClient_Subscribe_Call struct {
// Subscribe is a helper method to define mock.On call // Subscribe is a helper method to define mock.On call
// - id string // - id string
func (_e *MockClient_Expecter) Subscribe(id interface{}) *MockClient_Subscribe_Call { func (_e *MockClient_Expecter) Subscribe(id any) *MockClient_Subscribe_Call {
return &MockClient_Subscribe_Call{Call: _e.mock.On("Subscribe", id)} return &MockClient_Subscribe_Call{Call: _e.mock.On("Subscribe", id)}
} }
func (_c *MockClient_Subscribe_Call) Run(run func(id string)) *MockClient_Subscribe_Call { func (_c *MockClient_Subscribe_Call) Run(run func(id string)) *MockClient_Subscribe_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockClient_Subscribe_Call) Return(_a0 chan geolocation.Location) *MockClient_Subscribe_Call { func (_c *MockClient_Subscribe_Call) Return(locationCh chan geolocation.Location) *MockClient_Subscribe_Call {
_c.Call.Return(_a0) _c.Call.Return(locationCh)
return _c return _c
} }
func (_c *MockClient_Subscribe_Call) RunAndReturn(run func(string) chan geolocation.Location) *MockClient_Subscribe_Call { func (_c *MockClient_Subscribe_Call) RunAndReturn(run func(id string) chan geolocation.Location) *MockClient_Subscribe_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Unsubscribe provides a mock function with given fields: id // Unsubscribe provides a mock function for the type MockClient
func (_m *MockClient) Unsubscribe(id string) { func (_mock *MockClient) Unsubscribe(id string) {
_m.Called(id) _mock.Called(id)
return
} }
// MockClient_Unsubscribe_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unsubscribe' // MockClient_Unsubscribe_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unsubscribe'
@@ -167,13 +188,19 @@ type MockClient_Unsubscribe_Call struct {
// Unsubscribe is a helper method to define mock.On call // Unsubscribe is a helper method to define mock.On call
// - id string // - id string
func (_e *MockClient_Expecter) Unsubscribe(id interface{}) *MockClient_Unsubscribe_Call { func (_e *MockClient_Expecter) Unsubscribe(id any) *MockClient_Unsubscribe_Call {
return &MockClient_Unsubscribe_Call{Call: _e.mock.On("Unsubscribe", id)} return &MockClient_Unsubscribe_Call{Call: _e.mock.On("Unsubscribe", id)}
} }
func (_c *MockClient_Unsubscribe_Call) Run(run func(id string)) *MockClient_Unsubscribe_Call { func (_c *MockClient_Unsubscribe_Call) Run(run func(id string)) *MockClient_Unsubscribe_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
@@ -183,21 +210,7 @@ func (_c *MockClient_Unsubscribe_Call) Return() *MockClient_Unsubscribe_Call {
return _c return _c
} }
func (_c *MockClient_Unsubscribe_Call) RunAndReturn(run func(string)) *MockClient_Unsubscribe_Call { func (_c *MockClient_Unsubscribe_Call) RunAndReturn(run func(id string)) *MockClient_Unsubscribe_Call {
_c.Run(run) _c.Run(run)
return _c return _c
} }
// NewMockClient creates a new instance of MockClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockClient(t interface {
mock.TestingT
Cleanup(func())
}) *MockClient {
mock := &MockClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -1,14 +1,29 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package gonetworkmanager package gonetworkmanager
import ( import (
gonetworkmanager "github.com/Wifx/gonetworkmanager/v2" "github.com/Wifx/gonetworkmanager/v2"
dbus "github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockAccessPoint creates a new instance of MockAccessPoint. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockAccessPoint(t interface {
mock.TestingT
Cleanup(func())
}) *MockAccessPoint {
mock := &MockAccessPoint{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockAccessPoint is an autogenerated mock type for the AccessPoint type // MockAccessPoint is an autogenerated mock type for the AccessPoint type
type MockAccessPoint struct { type MockAccessPoint struct {
mock.Mock mock.Mock
@@ -22,21 +37,20 @@ func (_m *MockAccessPoint) EXPECT() *MockAccessPoint_Expecter {
return &MockAccessPoint_Expecter{mock: &_m.Mock} return &MockAccessPoint_Expecter{mock: &_m.Mock}
} }
// GetPath provides a mock function with no fields // GetPath provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPath() dbus.ObjectPath { func (_mock *MockAccessPoint) GetPath() dbus.ObjectPath {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPath") panic("no return value specified for GetPath")
} }
var r0 dbus.ObjectPath var r0 dbus.ObjectPath
if rf, ok := ret.Get(0).(func() dbus.ObjectPath); ok { if returnFunc, ok := ret.Get(0).(func() dbus.ObjectPath); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(dbus.ObjectPath) r0 = ret.Get(0).(dbus.ObjectPath)
} }
return r0 return r0
} }
@@ -57,8 +71,8 @@ func (_c *MockAccessPoint_GetPath_Call) Run(run func()) *MockAccessPoint_GetPath
return _c return _c
} }
func (_c *MockAccessPoint_GetPath_Call) Return(_a0 dbus.ObjectPath) *MockAccessPoint_GetPath_Call { func (_c *MockAccessPoint_GetPath_Call) Return(objectPath dbus.ObjectPath) *MockAccessPoint_GetPath_Call {
_c.Call.Return(_a0) _c.Call.Return(objectPath)
return _c return _c
} }
@@ -67,9 +81,9 @@ func (_c *MockAccessPoint_GetPath_Call) RunAndReturn(run func() dbus.ObjectPath)
return _c return _c
} }
// GetPropertyFlags provides a mock function with no fields // GetPropertyFlags provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyFlags() (uint32, error) { func (_mock *MockAccessPoint) GetPropertyFlags() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyFlags") panic("no return value specified for GetPropertyFlags")
@@ -77,21 +91,19 @@ func (_m *MockAccessPoint) GetPropertyFlags() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -112,8 +124,8 @@ func (_c *MockAccessPoint_GetPropertyFlags_Call) Run(run func()) *MockAccessPoin
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyFlags_Call) Return(_a0 uint32, _a1 error) *MockAccessPoint_GetPropertyFlags_Call { func (_c *MockAccessPoint_GetPropertyFlags_Call) Return(v uint32, err error) *MockAccessPoint_GetPropertyFlags_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -122,9 +134,9 @@ func (_c *MockAccessPoint_GetPropertyFlags_Call) RunAndReturn(run func() (uint32
return _c return _c
} }
// GetPropertyFrequency provides a mock function with no fields // GetPropertyFrequency provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyFrequency() (uint32, error) { func (_mock *MockAccessPoint) GetPropertyFrequency() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyFrequency") panic("no return value specified for GetPropertyFrequency")
@@ -132,21 +144,19 @@ func (_m *MockAccessPoint) GetPropertyFrequency() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -167,8 +177,8 @@ func (_c *MockAccessPoint_GetPropertyFrequency_Call) Run(run func()) *MockAccess
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyFrequency_Call) Return(_a0 uint32, _a1 error) *MockAccessPoint_GetPropertyFrequency_Call { func (_c *MockAccessPoint_GetPropertyFrequency_Call) Return(v uint32, err error) *MockAccessPoint_GetPropertyFrequency_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -177,9 +187,9 @@ func (_c *MockAccessPoint_GetPropertyFrequency_Call) RunAndReturn(run func() (ui
return _c return _c
} }
// GetPropertyHWAddress provides a mock function with no fields // GetPropertyHWAddress provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyHWAddress() (string, error) { func (_mock *MockAccessPoint) GetPropertyHWAddress() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyHWAddress") panic("no return value specified for GetPropertyHWAddress")
@@ -187,21 +197,19 @@ func (_m *MockAccessPoint) GetPropertyHWAddress() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -222,8 +230,8 @@ func (_c *MockAccessPoint_GetPropertyHWAddress_Call) Run(run func()) *MockAccess
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyHWAddress_Call) Return(_a0 string, _a1 error) *MockAccessPoint_GetPropertyHWAddress_Call { func (_c *MockAccessPoint_GetPropertyHWAddress_Call) Return(s string, err error) *MockAccessPoint_GetPropertyHWAddress_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -232,9 +240,9 @@ func (_c *MockAccessPoint_GetPropertyHWAddress_Call) RunAndReturn(run func() (st
return _c return _c
} }
// GetPropertyLastSeen provides a mock function with no fields // GetPropertyLastSeen provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyLastSeen() (int32, error) { func (_mock *MockAccessPoint) GetPropertyLastSeen() (int32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyLastSeen") panic("no return value specified for GetPropertyLastSeen")
@@ -242,21 +250,19 @@ func (_m *MockAccessPoint) GetPropertyLastSeen() (int32, error) {
var r0 int32 var r0 int32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (int32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (int32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() int32); ok { if returnFunc, ok := ret.Get(0).(func() int32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(int32) r0 = ret.Get(0).(int32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -277,8 +283,8 @@ func (_c *MockAccessPoint_GetPropertyLastSeen_Call) Run(run func()) *MockAccessP
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyLastSeen_Call) Return(_a0 int32, _a1 error) *MockAccessPoint_GetPropertyLastSeen_Call { func (_c *MockAccessPoint_GetPropertyLastSeen_Call) Return(n int32, err error) *MockAccessPoint_GetPropertyLastSeen_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(n, err)
return _c return _c
} }
@@ -287,9 +293,9 @@ func (_c *MockAccessPoint_GetPropertyLastSeen_Call) RunAndReturn(run func() (int
return _c return _c
} }
// GetPropertyMaxBitrate provides a mock function with no fields // GetPropertyMaxBitrate provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyMaxBitrate() (uint32, error) { func (_mock *MockAccessPoint) GetPropertyMaxBitrate() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyMaxBitrate") panic("no return value specified for GetPropertyMaxBitrate")
@@ -297,21 +303,19 @@ func (_m *MockAccessPoint) GetPropertyMaxBitrate() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -332,8 +336,8 @@ func (_c *MockAccessPoint_GetPropertyMaxBitrate_Call) Run(run func()) *MockAcces
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyMaxBitrate_Call) Return(_a0 uint32, _a1 error) *MockAccessPoint_GetPropertyMaxBitrate_Call { func (_c *MockAccessPoint_GetPropertyMaxBitrate_Call) Return(v uint32, err error) *MockAccessPoint_GetPropertyMaxBitrate_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -342,9 +346,9 @@ func (_c *MockAccessPoint_GetPropertyMaxBitrate_Call) RunAndReturn(run func() (u
return _c return _c
} }
// GetPropertyMode provides a mock function with no fields // GetPropertyMode provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyMode() (gonetworkmanager.Nm80211Mode, error) { func (_mock *MockAccessPoint) GetPropertyMode() (gonetworkmanager.Nm80211Mode, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyMode") panic("no return value specified for GetPropertyMode")
@@ -352,21 +356,19 @@ func (_m *MockAccessPoint) GetPropertyMode() (gonetworkmanager.Nm80211Mode, erro
var r0 gonetworkmanager.Nm80211Mode var r0 gonetworkmanager.Nm80211Mode
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.Nm80211Mode, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.Nm80211Mode, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.Nm80211Mode); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.Nm80211Mode); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(gonetworkmanager.Nm80211Mode) r0 = ret.Get(0).(gonetworkmanager.Nm80211Mode)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -387,8 +389,8 @@ func (_c *MockAccessPoint_GetPropertyMode_Call) Run(run func()) *MockAccessPoint
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyMode_Call) Return(_a0 gonetworkmanager.Nm80211Mode, _a1 error) *MockAccessPoint_GetPropertyMode_Call { func (_c *MockAccessPoint_GetPropertyMode_Call) Return(nm80211Mode gonetworkmanager.Nm80211Mode, err error) *MockAccessPoint_GetPropertyMode_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(nm80211Mode, err)
return _c return _c
} }
@@ -397,9 +399,9 @@ func (_c *MockAccessPoint_GetPropertyMode_Call) RunAndReturn(run func() (gonetwo
return _c return _c
} }
// GetPropertyRSNFlags provides a mock function with no fields // GetPropertyRSNFlags provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyRSNFlags() (uint32, error) { func (_mock *MockAccessPoint) GetPropertyRSNFlags() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyRSNFlags") panic("no return value specified for GetPropertyRSNFlags")
@@ -407,21 +409,19 @@ func (_m *MockAccessPoint) GetPropertyRSNFlags() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -442,8 +442,8 @@ func (_c *MockAccessPoint_GetPropertyRSNFlags_Call) Run(run func()) *MockAccessP
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyRSNFlags_Call) Return(_a0 uint32, _a1 error) *MockAccessPoint_GetPropertyRSNFlags_Call { func (_c *MockAccessPoint_GetPropertyRSNFlags_Call) Return(v uint32, err error) *MockAccessPoint_GetPropertyRSNFlags_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -452,9 +452,9 @@ func (_c *MockAccessPoint_GetPropertyRSNFlags_Call) RunAndReturn(run func() (uin
return _c return _c
} }
// GetPropertySSID provides a mock function with no fields // GetPropertySSID provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertySSID() (string, error) { func (_mock *MockAccessPoint) GetPropertySSID() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertySSID") panic("no return value specified for GetPropertySSID")
@@ -462,21 +462,19 @@ func (_m *MockAccessPoint) GetPropertySSID() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -497,8 +495,8 @@ func (_c *MockAccessPoint_GetPropertySSID_Call) Run(run func()) *MockAccessPoint
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertySSID_Call) Return(_a0 string, _a1 error) *MockAccessPoint_GetPropertySSID_Call { func (_c *MockAccessPoint_GetPropertySSID_Call) Return(s string, err error) *MockAccessPoint_GetPropertySSID_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -507,9 +505,9 @@ func (_c *MockAccessPoint_GetPropertySSID_Call) RunAndReturn(run func() (string,
return _c return _c
} }
// GetPropertyStrength provides a mock function with no fields // GetPropertyStrength provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyStrength() (uint8, error) { func (_mock *MockAccessPoint) GetPropertyStrength() (uint8, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyStrength") panic("no return value specified for GetPropertyStrength")
@@ -517,21 +515,19 @@ func (_m *MockAccessPoint) GetPropertyStrength() (uint8, error) {
var r0 uint8 var r0 uint8
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint8, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint8, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint8); ok { if returnFunc, ok := ret.Get(0).(func() uint8); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint8) r0 = ret.Get(0).(uint8)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -552,8 +548,8 @@ func (_c *MockAccessPoint_GetPropertyStrength_Call) Run(run func()) *MockAccessP
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyStrength_Call) Return(_a0 uint8, _a1 error) *MockAccessPoint_GetPropertyStrength_Call { func (_c *MockAccessPoint_GetPropertyStrength_Call) Return(v uint8, err error) *MockAccessPoint_GetPropertyStrength_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -562,9 +558,9 @@ func (_c *MockAccessPoint_GetPropertyStrength_Call) RunAndReturn(run func() (uin
return _c return _c
} }
// GetPropertyWPAFlags provides a mock function with no fields // GetPropertyWPAFlags provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) GetPropertyWPAFlags() (uint32, error) { func (_mock *MockAccessPoint) GetPropertyWPAFlags() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyWPAFlags") panic("no return value specified for GetPropertyWPAFlags")
@@ -572,21 +568,19 @@ func (_m *MockAccessPoint) GetPropertyWPAFlags() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -607,8 +601,8 @@ func (_c *MockAccessPoint_GetPropertyWPAFlags_Call) Run(run func()) *MockAccessP
return _c return _c
} }
func (_c *MockAccessPoint_GetPropertyWPAFlags_Call) Return(_a0 uint32, _a1 error) *MockAccessPoint_GetPropertyWPAFlags_Call { func (_c *MockAccessPoint_GetPropertyWPAFlags_Call) Return(v uint32, err error) *MockAccessPoint_GetPropertyWPAFlags_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -617,9 +611,9 @@ func (_c *MockAccessPoint_GetPropertyWPAFlags_Call) RunAndReturn(run func() (uin
return _c return _c
} }
// MarshalJSON provides a mock function with no fields // MarshalJSON provides a mock function for the type MockAccessPoint
func (_m *MockAccessPoint) MarshalJSON() ([]byte, error) { func (_mock *MockAccessPoint) MarshalJSON() ([]byte, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for MarshalJSON") panic("no return value specified for MarshalJSON")
@@ -627,23 +621,21 @@ func (_m *MockAccessPoint) MarshalJSON() ([]byte, error) {
var r0 []byte var r0 []byte
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]byte, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]byte, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []byte); ok { if returnFunc, ok := ret.Get(0).(func() []byte); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte) r0 = ret.Get(0).([]byte)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -664,8 +656,8 @@ func (_c *MockAccessPoint_MarshalJSON_Call) Run(run func()) *MockAccessPoint_Mar
return _c return _c
} }
func (_c *MockAccessPoint_MarshalJSON_Call) Return(_a0 []byte, _a1 error) *MockAccessPoint_MarshalJSON_Call { func (_c *MockAccessPoint_MarshalJSON_Call) Return(bytes []byte, err error) *MockAccessPoint_MarshalJSON_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(bytes, err)
return _c return _c
} }
@@ -673,17 +665,3 @@ func (_c *MockAccessPoint_MarshalJSON_Call) RunAndReturn(run func() ([]byte, err
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockAccessPoint creates a new instance of MockAccessPoint. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockAccessPoint(t interface {
mock.TestingT
Cleanup(func())
}) *MockAccessPoint {
mock := &MockAccessPoint{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -1,14 +1,29 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package gonetworkmanager package gonetworkmanager
import ( import (
gonetworkmanager "github.com/Wifx/gonetworkmanager/v2" "github.com/Wifx/gonetworkmanager/v2"
dbus "github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockActiveConnection creates a new instance of MockActiveConnection. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockActiveConnection(t interface {
mock.TestingT
Cleanup(func())
}) *MockActiveConnection {
mock := &MockActiveConnection{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockActiveConnection is an autogenerated mock type for the ActiveConnection type // MockActiveConnection is an autogenerated mock type for the ActiveConnection type
type MockActiveConnection struct { type MockActiveConnection struct {
mock.Mock mock.Mock
@@ -22,21 +37,20 @@ func (_m *MockActiveConnection) EXPECT() *MockActiveConnection_Expecter {
return &MockActiveConnection_Expecter{mock: &_m.Mock} return &MockActiveConnection_Expecter{mock: &_m.Mock}
} }
// GetPath provides a mock function with no fields // GetPath provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPath() dbus.ObjectPath { func (_mock *MockActiveConnection) GetPath() dbus.ObjectPath {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPath") panic("no return value specified for GetPath")
} }
var r0 dbus.ObjectPath var r0 dbus.ObjectPath
if rf, ok := ret.Get(0).(func() dbus.ObjectPath); ok { if returnFunc, ok := ret.Get(0).(func() dbus.ObjectPath); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(dbus.ObjectPath) r0 = ret.Get(0).(dbus.ObjectPath)
} }
return r0 return r0
} }
@@ -57,8 +71,8 @@ func (_c *MockActiveConnection_GetPath_Call) Run(run func()) *MockActiveConnecti
return _c return _c
} }
func (_c *MockActiveConnection_GetPath_Call) Return(_a0 dbus.ObjectPath) *MockActiveConnection_GetPath_Call { func (_c *MockActiveConnection_GetPath_Call) Return(objectPath dbus.ObjectPath) *MockActiveConnection_GetPath_Call {
_c.Call.Return(_a0) _c.Call.Return(objectPath)
return _c return _c
} }
@@ -67,9 +81,9 @@ func (_c *MockActiveConnection_GetPath_Call) RunAndReturn(run func() dbus.Object
return _c return _c
} }
// GetPropertyConnection provides a mock function with no fields // GetPropertyConnection provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyConnection() (gonetworkmanager.Connection, error) { func (_mock *MockActiveConnection) GetPropertyConnection() (gonetworkmanager.Connection, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyConnection") panic("no return value specified for GetPropertyConnection")
@@ -77,23 +91,21 @@ func (_m *MockActiveConnection) GetPropertyConnection() (gonetworkmanager.Connec
var r0 gonetworkmanager.Connection var r0 gonetworkmanager.Connection
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.Connection, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.Connection, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.Connection); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.Connection); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.Connection) r0 = ret.Get(0).(gonetworkmanager.Connection)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -114,8 +126,8 @@ func (_c *MockActiveConnection_GetPropertyConnection_Call) Run(run func()) *Mock
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyConnection_Call) Return(_a0 gonetworkmanager.Connection, _a1 error) *MockActiveConnection_GetPropertyConnection_Call { func (_c *MockActiveConnection_GetPropertyConnection_Call) Return(connection gonetworkmanager.Connection, err error) *MockActiveConnection_GetPropertyConnection_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connection, err)
return _c return _c
} }
@@ -124,9 +136,9 @@ func (_c *MockActiveConnection_GetPropertyConnection_Call) RunAndReturn(run func
return _c return _c
} }
// GetPropertyDHCP4Config provides a mock function with no fields // GetPropertyDHCP4Config provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyDHCP4Config() (gonetworkmanager.DHCP4Config, error) { func (_mock *MockActiveConnection) GetPropertyDHCP4Config() (gonetworkmanager.DHCP4Config, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDHCP4Config") panic("no return value specified for GetPropertyDHCP4Config")
@@ -134,23 +146,21 @@ func (_m *MockActiveConnection) GetPropertyDHCP4Config() (gonetworkmanager.DHCP4
var r0 gonetworkmanager.DHCP4Config var r0 gonetworkmanager.DHCP4Config
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.DHCP4Config, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.DHCP4Config, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.DHCP4Config); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.DHCP4Config); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.DHCP4Config) r0 = ret.Get(0).(gonetworkmanager.DHCP4Config)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -171,8 +181,8 @@ func (_c *MockActiveConnection_GetPropertyDHCP4Config_Call) Run(run func()) *Moc
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyDHCP4Config_Call) Return(_a0 gonetworkmanager.DHCP4Config, _a1 error) *MockActiveConnection_GetPropertyDHCP4Config_Call { func (_c *MockActiveConnection_GetPropertyDHCP4Config_Call) Return(dHCP4Config gonetworkmanager.DHCP4Config, err error) *MockActiveConnection_GetPropertyDHCP4Config_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(dHCP4Config, err)
return _c return _c
} }
@@ -181,9 +191,9 @@ func (_c *MockActiveConnection_GetPropertyDHCP4Config_Call) RunAndReturn(run fun
return _c return _c
} }
// GetPropertyDHCP6Config provides a mock function with no fields // GetPropertyDHCP6Config provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyDHCP6Config() (gonetworkmanager.DHCP6Config, error) { func (_mock *MockActiveConnection) GetPropertyDHCP6Config() (gonetworkmanager.DHCP6Config, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDHCP6Config") panic("no return value specified for GetPropertyDHCP6Config")
@@ -191,23 +201,21 @@ func (_m *MockActiveConnection) GetPropertyDHCP6Config() (gonetworkmanager.DHCP6
var r0 gonetworkmanager.DHCP6Config var r0 gonetworkmanager.DHCP6Config
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.DHCP6Config, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.DHCP6Config, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.DHCP6Config); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.DHCP6Config); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.DHCP6Config) r0 = ret.Get(0).(gonetworkmanager.DHCP6Config)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -228,8 +236,8 @@ func (_c *MockActiveConnection_GetPropertyDHCP6Config_Call) Run(run func()) *Moc
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyDHCP6Config_Call) Return(_a0 gonetworkmanager.DHCP6Config, _a1 error) *MockActiveConnection_GetPropertyDHCP6Config_Call { func (_c *MockActiveConnection_GetPropertyDHCP6Config_Call) Return(dHCP6Config gonetworkmanager.DHCP6Config, err error) *MockActiveConnection_GetPropertyDHCP6Config_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(dHCP6Config, err)
return _c return _c
} }
@@ -238,9 +246,9 @@ func (_c *MockActiveConnection_GetPropertyDHCP6Config_Call) RunAndReturn(run fun
return _c return _c
} }
// GetPropertyDefault provides a mock function with no fields // GetPropertyDefault provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyDefault() (bool, error) { func (_mock *MockActiveConnection) GetPropertyDefault() (bool, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDefault") panic("no return value specified for GetPropertyDefault")
@@ -248,21 +256,19 @@ func (_m *MockActiveConnection) GetPropertyDefault() (bool, error) {
var r0 bool var r0 bool
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (bool, error)); ok { if returnFunc, ok := ret.Get(0).(func() (bool, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() bool); ok { if returnFunc, ok := ret.Get(0).(func() bool); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(bool) r0 = ret.Get(0).(bool)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -283,8 +289,8 @@ func (_c *MockActiveConnection_GetPropertyDefault_Call) Run(run func()) *MockAct
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyDefault_Call) Return(_a0 bool, _a1 error) *MockActiveConnection_GetPropertyDefault_Call { func (_c *MockActiveConnection_GetPropertyDefault_Call) Return(b bool, err error) *MockActiveConnection_GetPropertyDefault_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(b, err)
return _c return _c
} }
@@ -293,9 +299,9 @@ func (_c *MockActiveConnection_GetPropertyDefault_Call) RunAndReturn(run func()
return _c return _c
} }
// GetPropertyDefault6 provides a mock function with no fields // GetPropertyDefault6 provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyDefault6() (bool, error) { func (_mock *MockActiveConnection) GetPropertyDefault6() (bool, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDefault6") panic("no return value specified for GetPropertyDefault6")
@@ -303,21 +309,19 @@ func (_m *MockActiveConnection) GetPropertyDefault6() (bool, error) {
var r0 bool var r0 bool
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (bool, error)); ok { if returnFunc, ok := ret.Get(0).(func() (bool, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() bool); ok { if returnFunc, ok := ret.Get(0).(func() bool); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(bool) r0 = ret.Get(0).(bool)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -338,8 +342,8 @@ func (_c *MockActiveConnection_GetPropertyDefault6_Call) Run(run func()) *MockAc
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyDefault6_Call) Return(_a0 bool, _a1 error) *MockActiveConnection_GetPropertyDefault6_Call { func (_c *MockActiveConnection_GetPropertyDefault6_Call) Return(b bool, err error) *MockActiveConnection_GetPropertyDefault6_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(b, err)
return _c return _c
} }
@@ -348,9 +352,9 @@ func (_c *MockActiveConnection_GetPropertyDefault6_Call) RunAndReturn(run func()
return _c return _c
} }
// GetPropertyDevices provides a mock function with no fields // GetPropertyDevices provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyDevices() ([]gonetworkmanager.Device, error) { func (_mock *MockActiveConnection) GetPropertyDevices() ([]gonetworkmanager.Device, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDevices") panic("no return value specified for GetPropertyDevices")
@@ -358,23 +362,21 @@ func (_m *MockActiveConnection) GetPropertyDevices() ([]gonetworkmanager.Device,
var r0 []gonetworkmanager.Device var r0 []gonetworkmanager.Device
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.Device, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.Device, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.Device); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.Device); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.Device) r0 = ret.Get(0).([]gonetworkmanager.Device)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -395,8 +397,8 @@ func (_c *MockActiveConnection_GetPropertyDevices_Call) Run(run func()) *MockAct
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyDevices_Call) Return(_a0 []gonetworkmanager.Device, _a1 error) *MockActiveConnection_GetPropertyDevices_Call { func (_c *MockActiveConnection_GetPropertyDevices_Call) Return(devices []gonetworkmanager.Device, err error) *MockActiveConnection_GetPropertyDevices_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(devices, err)
return _c return _c
} }
@@ -405,9 +407,9 @@ func (_c *MockActiveConnection_GetPropertyDevices_Call) RunAndReturn(run func()
return _c return _c
} }
// GetPropertyID provides a mock function with no fields // GetPropertyID provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyID() (string, error) { func (_mock *MockActiveConnection) GetPropertyID() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyID") panic("no return value specified for GetPropertyID")
@@ -415,21 +417,19 @@ func (_m *MockActiveConnection) GetPropertyID() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -450,8 +450,8 @@ func (_c *MockActiveConnection_GetPropertyID_Call) Run(run func()) *MockActiveCo
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyID_Call) Return(_a0 string, _a1 error) *MockActiveConnection_GetPropertyID_Call { func (_c *MockActiveConnection_GetPropertyID_Call) Return(s string, err error) *MockActiveConnection_GetPropertyID_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -460,9 +460,9 @@ func (_c *MockActiveConnection_GetPropertyID_Call) RunAndReturn(run func() (stri
return _c return _c
} }
// GetPropertyIP4Config provides a mock function with no fields // GetPropertyIP4Config provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyIP4Config() (gonetworkmanager.IP4Config, error) { func (_mock *MockActiveConnection) GetPropertyIP4Config() (gonetworkmanager.IP4Config, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyIP4Config") panic("no return value specified for GetPropertyIP4Config")
@@ -470,23 +470,21 @@ func (_m *MockActiveConnection) GetPropertyIP4Config() (gonetworkmanager.IP4Conf
var r0 gonetworkmanager.IP4Config var r0 gonetworkmanager.IP4Config
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.IP4Config, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.IP4Config, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.IP4Config); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.IP4Config); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.IP4Config) r0 = ret.Get(0).(gonetworkmanager.IP4Config)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -507,8 +505,8 @@ func (_c *MockActiveConnection_GetPropertyIP4Config_Call) Run(run func()) *MockA
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyIP4Config_Call) Return(_a0 gonetworkmanager.IP4Config, _a1 error) *MockActiveConnection_GetPropertyIP4Config_Call { func (_c *MockActiveConnection_GetPropertyIP4Config_Call) Return(iP4Config gonetworkmanager.IP4Config, err error) *MockActiveConnection_GetPropertyIP4Config_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP4Config, err)
return _c return _c
} }
@@ -517,9 +515,9 @@ func (_c *MockActiveConnection_GetPropertyIP4Config_Call) RunAndReturn(run func(
return _c return _c
} }
// GetPropertyIP6Config provides a mock function with no fields // GetPropertyIP6Config provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyIP6Config() (gonetworkmanager.IP6Config, error) { func (_mock *MockActiveConnection) GetPropertyIP6Config() (gonetworkmanager.IP6Config, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyIP6Config") panic("no return value specified for GetPropertyIP6Config")
@@ -527,23 +525,21 @@ func (_m *MockActiveConnection) GetPropertyIP6Config() (gonetworkmanager.IP6Conf
var r0 gonetworkmanager.IP6Config var r0 gonetworkmanager.IP6Config
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.IP6Config, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.IP6Config, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.IP6Config); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.IP6Config); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.IP6Config) r0 = ret.Get(0).(gonetworkmanager.IP6Config)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -564,8 +560,8 @@ func (_c *MockActiveConnection_GetPropertyIP6Config_Call) Run(run func()) *MockA
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyIP6Config_Call) Return(_a0 gonetworkmanager.IP6Config, _a1 error) *MockActiveConnection_GetPropertyIP6Config_Call { func (_c *MockActiveConnection_GetPropertyIP6Config_Call) Return(iP6Config gonetworkmanager.IP6Config, err error) *MockActiveConnection_GetPropertyIP6Config_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP6Config, err)
return _c return _c
} }
@@ -574,9 +570,9 @@ func (_c *MockActiveConnection_GetPropertyIP6Config_Call) RunAndReturn(run func(
return _c return _c
} }
// GetPropertyMaster provides a mock function with no fields // GetPropertyMaster provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyMaster() (gonetworkmanager.Device, error) { func (_mock *MockActiveConnection) GetPropertyMaster() (gonetworkmanager.Device, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyMaster") panic("no return value specified for GetPropertyMaster")
@@ -584,23 +580,21 @@ func (_m *MockActiveConnection) GetPropertyMaster() (gonetworkmanager.Device, er
var r0 gonetworkmanager.Device var r0 gonetworkmanager.Device
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.Device, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.Device, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.Device); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.Device); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.Device) r0 = ret.Get(0).(gonetworkmanager.Device)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -621,8 +615,8 @@ func (_c *MockActiveConnection_GetPropertyMaster_Call) Run(run func()) *MockActi
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyMaster_Call) Return(_a0 gonetworkmanager.Device, _a1 error) *MockActiveConnection_GetPropertyMaster_Call { func (_c *MockActiveConnection_GetPropertyMaster_Call) Return(device gonetworkmanager.Device, err error) *MockActiveConnection_GetPropertyMaster_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(device, err)
return _c return _c
} }
@@ -631,9 +625,9 @@ func (_c *MockActiveConnection_GetPropertyMaster_Call) RunAndReturn(run func() (
return _c return _c
} }
// GetPropertySpecificObject provides a mock function with no fields // GetPropertySpecificObject provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertySpecificObject() (gonetworkmanager.AccessPoint, error) { func (_mock *MockActiveConnection) GetPropertySpecificObject() (gonetworkmanager.AccessPoint, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertySpecificObject") panic("no return value specified for GetPropertySpecificObject")
@@ -641,23 +635,21 @@ func (_m *MockActiveConnection) GetPropertySpecificObject() (gonetworkmanager.Ac
var r0 gonetworkmanager.AccessPoint var r0 gonetworkmanager.AccessPoint
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.AccessPoint, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.AccessPoint, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.AccessPoint); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.AccessPoint); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.AccessPoint) r0 = ret.Get(0).(gonetworkmanager.AccessPoint)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -678,8 +670,8 @@ func (_c *MockActiveConnection_GetPropertySpecificObject_Call) Run(run func()) *
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertySpecificObject_Call) Return(_a0 gonetworkmanager.AccessPoint, _a1 error) *MockActiveConnection_GetPropertySpecificObject_Call { func (_c *MockActiveConnection_GetPropertySpecificObject_Call) Return(accessPoint gonetworkmanager.AccessPoint, err error) *MockActiveConnection_GetPropertySpecificObject_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(accessPoint, err)
return _c return _c
} }
@@ -688,9 +680,9 @@ func (_c *MockActiveConnection_GetPropertySpecificObject_Call) RunAndReturn(run
return _c return _c
} }
// GetPropertyState provides a mock function with no fields // GetPropertyState provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyState() (gonetworkmanager.NmActiveConnectionState, error) { func (_mock *MockActiveConnection) GetPropertyState() (gonetworkmanager.NmActiveConnectionState, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyState") panic("no return value specified for GetPropertyState")
@@ -698,21 +690,19 @@ func (_m *MockActiveConnection) GetPropertyState() (gonetworkmanager.NmActiveCon
var r0 gonetworkmanager.NmActiveConnectionState var r0 gonetworkmanager.NmActiveConnectionState
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.NmActiveConnectionState, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.NmActiveConnectionState, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.NmActiveConnectionState); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.NmActiveConnectionState); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(gonetworkmanager.NmActiveConnectionState) r0 = ret.Get(0).(gonetworkmanager.NmActiveConnectionState)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -733,8 +723,8 @@ func (_c *MockActiveConnection_GetPropertyState_Call) Run(run func()) *MockActiv
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyState_Call) Return(_a0 gonetworkmanager.NmActiveConnectionState, _a1 error) *MockActiveConnection_GetPropertyState_Call { func (_c *MockActiveConnection_GetPropertyState_Call) Return(nmActiveConnectionState gonetworkmanager.NmActiveConnectionState, err error) *MockActiveConnection_GetPropertyState_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(nmActiveConnectionState, err)
return _c return _c
} }
@@ -743,9 +733,9 @@ func (_c *MockActiveConnection_GetPropertyState_Call) RunAndReturn(run func() (g
return _c return _c
} }
// GetPropertyStateFlags provides a mock function with no fields // GetPropertyStateFlags provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyStateFlags() (uint32, error) { func (_mock *MockActiveConnection) GetPropertyStateFlags() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyStateFlags") panic("no return value specified for GetPropertyStateFlags")
@@ -753,21 +743,19 @@ func (_m *MockActiveConnection) GetPropertyStateFlags() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -788,8 +776,8 @@ func (_c *MockActiveConnection_GetPropertyStateFlags_Call) Run(run func()) *Mock
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyStateFlags_Call) Return(_a0 uint32, _a1 error) *MockActiveConnection_GetPropertyStateFlags_Call { func (_c *MockActiveConnection_GetPropertyStateFlags_Call) Return(v uint32, err error) *MockActiveConnection_GetPropertyStateFlags_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -798,9 +786,9 @@ func (_c *MockActiveConnection_GetPropertyStateFlags_Call) RunAndReturn(run func
return _c return _c
} }
// GetPropertyType provides a mock function with no fields // GetPropertyType provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyType() (string, error) { func (_mock *MockActiveConnection) GetPropertyType() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyType") panic("no return value specified for GetPropertyType")
@@ -808,21 +796,19 @@ func (_m *MockActiveConnection) GetPropertyType() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -843,8 +829,8 @@ func (_c *MockActiveConnection_GetPropertyType_Call) Run(run func()) *MockActive
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyType_Call) Return(_a0 string, _a1 error) *MockActiveConnection_GetPropertyType_Call { func (_c *MockActiveConnection_GetPropertyType_Call) Return(s string, err error) *MockActiveConnection_GetPropertyType_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -853,9 +839,9 @@ func (_c *MockActiveConnection_GetPropertyType_Call) RunAndReturn(run func() (st
return _c return _c
} }
// GetPropertyUUID provides a mock function with no fields // GetPropertyUUID provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyUUID() (string, error) { func (_mock *MockActiveConnection) GetPropertyUUID() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyUUID") panic("no return value specified for GetPropertyUUID")
@@ -863,21 +849,19 @@ func (_m *MockActiveConnection) GetPropertyUUID() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -898,8 +882,8 @@ func (_c *MockActiveConnection_GetPropertyUUID_Call) Run(run func()) *MockActive
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyUUID_Call) Return(_a0 string, _a1 error) *MockActiveConnection_GetPropertyUUID_Call { func (_c *MockActiveConnection_GetPropertyUUID_Call) Return(s string, err error) *MockActiveConnection_GetPropertyUUID_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -908,9 +892,9 @@ func (_c *MockActiveConnection_GetPropertyUUID_Call) RunAndReturn(run func() (st
return _c return _c
} }
// GetPropertyVPN provides a mock function with no fields // GetPropertyVPN provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) GetPropertyVPN() (bool, error) { func (_mock *MockActiveConnection) GetPropertyVPN() (bool, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyVPN") panic("no return value specified for GetPropertyVPN")
@@ -918,21 +902,19 @@ func (_m *MockActiveConnection) GetPropertyVPN() (bool, error) {
var r0 bool var r0 bool
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (bool, error)); ok { if returnFunc, ok := ret.Get(0).(func() (bool, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() bool); ok { if returnFunc, ok := ret.Get(0).(func() bool); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(bool) r0 = ret.Get(0).(bool)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -953,8 +935,8 @@ func (_c *MockActiveConnection_GetPropertyVPN_Call) Run(run func()) *MockActiveC
return _c return _c
} }
func (_c *MockActiveConnection_GetPropertyVPN_Call) Return(_a0 bool, _a1 error) *MockActiveConnection_GetPropertyVPN_Call { func (_c *MockActiveConnection_GetPropertyVPN_Call) Return(b bool, err error) *MockActiveConnection_GetPropertyVPN_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(b, err)
return _c return _c
} }
@@ -963,21 +945,20 @@ func (_c *MockActiveConnection_GetPropertyVPN_Call) RunAndReturn(run func() (boo
return _c return _c
} }
// SubscribeState provides a mock function with given fields: receiver, exit // SubscribeState provides a mock function for the type MockActiveConnection
func (_m *MockActiveConnection) SubscribeState(receiver chan gonetworkmanager.StateChange, exit chan struct{}) error { func (_mock *MockActiveConnection) SubscribeState(receiver chan gonetworkmanager.StateChange, exit chan struct{}) error {
ret := _m.Called(receiver, exit) ret := _mock.Called(receiver, exit)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for SubscribeState") panic("no return value specified for SubscribeState")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(chan gonetworkmanager.StateChange, chan struct{}) error); ok { if returnFunc, ok := ret.Get(0).(func(chan gonetworkmanager.StateChange, chan struct{}) error); ok {
r0 = rf(receiver, exit) r0 = returnFunc(receiver, exit)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -989,13 +970,24 @@ type MockActiveConnection_SubscribeState_Call struct {
// SubscribeState is a helper method to define mock.On call // SubscribeState is a helper method to define mock.On call
// - receiver chan gonetworkmanager.StateChange // - receiver chan gonetworkmanager.StateChange
// - exit chan struct{} // - exit chan struct{}
func (_e *MockActiveConnection_Expecter) SubscribeState(receiver interface{}, exit interface{}) *MockActiveConnection_SubscribeState_Call { func (_e *MockActiveConnection_Expecter) SubscribeState(receiver any, exit any) *MockActiveConnection_SubscribeState_Call {
return &MockActiveConnection_SubscribeState_Call{Call: _e.mock.On("SubscribeState", receiver, exit)} return &MockActiveConnection_SubscribeState_Call{Call: _e.mock.On("SubscribeState", receiver, exit)}
} }
func (_c *MockActiveConnection_SubscribeState_Call) Run(run func(receiver chan gonetworkmanager.StateChange, exit chan struct{})) *MockActiveConnection_SubscribeState_Call { func (_c *MockActiveConnection_SubscribeState_Call) Run(run func(receiver chan gonetworkmanager.StateChange, exit chan struct{})) *MockActiveConnection_SubscribeState_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(chan gonetworkmanager.StateChange), args[1].(chan struct{})) var arg0 chan gonetworkmanager.StateChange
if args[0] != nil {
arg0 = args[0].(chan gonetworkmanager.StateChange)
}
var arg1 chan struct{}
if args[1] != nil {
arg1 = args[1].(chan struct{})
}
run(
arg0,
arg1,
)
}) })
return _c return _c
} }
@@ -1005,21 +997,7 @@ func (_c *MockActiveConnection_SubscribeState_Call) Return(err error) *MockActiv
return _c return _c
} }
func (_c *MockActiveConnection_SubscribeState_Call) RunAndReturn(run func(chan gonetworkmanager.StateChange, chan struct{}) error) *MockActiveConnection_SubscribeState_Call { func (_c *MockActiveConnection_SubscribeState_Call) RunAndReturn(run func(receiver chan gonetworkmanager.StateChange, exit chan struct{}) error) *MockActiveConnection_SubscribeState_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockActiveConnection creates a new instance of MockActiveConnection. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockActiveConnection(t interface {
mock.TestingT
Cleanup(func())
}) *MockActiveConnection {
mock := &MockActiveConnection{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -1,14 +1,29 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package gonetworkmanager package gonetworkmanager
import ( import (
gonetworkmanager "github.com/Wifx/gonetworkmanager/v2" "github.com/Wifx/gonetworkmanager/v2"
dbus "github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockConnection creates a new instance of MockConnection. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockConnection(t interface {
mock.TestingT
Cleanup(func())
}) *MockConnection {
mock := &MockConnection{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockConnection is an autogenerated mock type for the Connection type // MockConnection is an autogenerated mock type for the Connection type
type MockConnection struct { type MockConnection struct {
mock.Mock mock.Mock
@@ -22,21 +37,20 @@ func (_m *MockConnection) EXPECT() *MockConnection_Expecter {
return &MockConnection_Expecter{mock: &_m.Mock} return &MockConnection_Expecter{mock: &_m.Mock}
} }
// ClearSecrets provides a mock function with no fields // ClearSecrets provides a mock function for the type MockConnection
func (_m *MockConnection) ClearSecrets() error { func (_mock *MockConnection) ClearSecrets() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for ClearSecrets") panic("no return value specified for ClearSecrets")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -57,8 +71,8 @@ func (_c *MockConnection_ClearSecrets_Call) Run(run func()) *MockConnection_Clea
return _c return _c
} }
func (_c *MockConnection_ClearSecrets_Call) Return(_a0 error) *MockConnection_ClearSecrets_Call { func (_c *MockConnection_ClearSecrets_Call) Return(err error) *MockConnection_ClearSecrets_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -67,21 +81,20 @@ func (_c *MockConnection_ClearSecrets_Call) RunAndReturn(run func() error) *Mock
return _c return _c
} }
// Delete provides a mock function with no fields // Delete provides a mock function for the type MockConnection
func (_m *MockConnection) Delete() error { func (_mock *MockConnection) Delete() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Delete") panic("no return value specified for Delete")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -102,8 +115,8 @@ func (_c *MockConnection_Delete_Call) Run(run func()) *MockConnection_Delete_Cal
return _c return _c
} }
func (_c *MockConnection_Delete_Call) Return(_a0 error) *MockConnection_Delete_Call { func (_c *MockConnection_Delete_Call) Return(err error) *MockConnection_Delete_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -112,21 +125,20 @@ func (_c *MockConnection_Delete_Call) RunAndReturn(run func() error) *MockConnec
return _c return _c
} }
// GetPath provides a mock function with no fields // GetPath provides a mock function for the type MockConnection
func (_m *MockConnection) GetPath() dbus.ObjectPath { func (_mock *MockConnection) GetPath() dbus.ObjectPath {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPath") panic("no return value specified for GetPath")
} }
var r0 dbus.ObjectPath var r0 dbus.ObjectPath
if rf, ok := ret.Get(0).(func() dbus.ObjectPath); ok { if returnFunc, ok := ret.Get(0).(func() dbus.ObjectPath); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(dbus.ObjectPath) r0 = ret.Get(0).(dbus.ObjectPath)
} }
return r0 return r0
} }
@@ -147,8 +159,8 @@ func (_c *MockConnection_GetPath_Call) Run(run func()) *MockConnection_GetPath_C
return _c return _c
} }
func (_c *MockConnection_GetPath_Call) Return(_a0 dbus.ObjectPath) *MockConnection_GetPath_Call { func (_c *MockConnection_GetPath_Call) Return(objectPath dbus.ObjectPath) *MockConnection_GetPath_Call {
_c.Call.Return(_a0) _c.Call.Return(objectPath)
return _c return _c
} }
@@ -157,9 +169,9 @@ func (_c *MockConnection_GetPath_Call) RunAndReturn(run func() dbus.ObjectPath)
return _c return _c
} }
// GetPropertyFilename provides a mock function with no fields // GetPropertyFilename provides a mock function for the type MockConnection
func (_m *MockConnection) GetPropertyFilename() (string, error) { func (_mock *MockConnection) GetPropertyFilename() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyFilename") panic("no return value specified for GetPropertyFilename")
@@ -167,21 +179,19 @@ func (_m *MockConnection) GetPropertyFilename() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -202,8 +212,8 @@ func (_c *MockConnection_GetPropertyFilename_Call) Run(run func()) *MockConnecti
return _c return _c
} }
func (_c *MockConnection_GetPropertyFilename_Call) Return(_a0 string, _a1 error) *MockConnection_GetPropertyFilename_Call { func (_c *MockConnection_GetPropertyFilename_Call) Return(s string, err error) *MockConnection_GetPropertyFilename_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -212,9 +222,9 @@ func (_c *MockConnection_GetPropertyFilename_Call) RunAndReturn(run func() (stri
return _c return _c
} }
// GetPropertyFlags provides a mock function with no fields // GetPropertyFlags provides a mock function for the type MockConnection
func (_m *MockConnection) GetPropertyFlags() (uint32, error) { func (_mock *MockConnection) GetPropertyFlags() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyFlags") panic("no return value specified for GetPropertyFlags")
@@ -222,21 +232,19 @@ func (_m *MockConnection) GetPropertyFlags() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -257,8 +265,8 @@ func (_c *MockConnection_GetPropertyFlags_Call) Run(run func()) *MockConnection_
return _c return _c
} }
func (_c *MockConnection_GetPropertyFlags_Call) Return(_a0 uint32, _a1 error) *MockConnection_GetPropertyFlags_Call { func (_c *MockConnection_GetPropertyFlags_Call) Return(v uint32, err error) *MockConnection_GetPropertyFlags_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -267,9 +275,9 @@ func (_c *MockConnection_GetPropertyFlags_Call) RunAndReturn(run func() (uint32,
return _c return _c
} }
// GetPropertyUnsaved provides a mock function with no fields // GetPropertyUnsaved provides a mock function for the type MockConnection
func (_m *MockConnection) GetPropertyUnsaved() (bool, error) { func (_mock *MockConnection) GetPropertyUnsaved() (bool, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyUnsaved") panic("no return value specified for GetPropertyUnsaved")
@@ -277,21 +285,19 @@ func (_m *MockConnection) GetPropertyUnsaved() (bool, error) {
var r0 bool var r0 bool
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (bool, error)); ok { if returnFunc, ok := ret.Get(0).(func() (bool, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() bool); ok { if returnFunc, ok := ret.Get(0).(func() bool); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(bool) r0 = ret.Get(0).(bool)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -312,8 +318,8 @@ func (_c *MockConnection_GetPropertyUnsaved_Call) Run(run func()) *MockConnectio
return _c return _c
} }
func (_c *MockConnection_GetPropertyUnsaved_Call) Return(_a0 bool, _a1 error) *MockConnection_GetPropertyUnsaved_Call { func (_c *MockConnection_GetPropertyUnsaved_Call) Return(b bool, err error) *MockConnection_GetPropertyUnsaved_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(b, err)
return _c return _c
} }
@@ -322,9 +328,9 @@ func (_c *MockConnection_GetPropertyUnsaved_Call) RunAndReturn(run func() (bool,
return _c return _c
} }
// GetSecrets provides a mock function with given fields: settingName // GetSecrets provides a mock function for the type MockConnection
func (_m *MockConnection) GetSecrets(settingName string) (gonetworkmanager.ConnectionSettings, error) { func (_mock *MockConnection) GetSecrets(settingName string) (gonetworkmanager.ConnectionSettings, error) {
ret := _m.Called(settingName) ret := _mock.Called(settingName)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetSecrets") panic("no return value specified for GetSecrets")
@@ -332,23 +338,21 @@ func (_m *MockConnection) GetSecrets(settingName string) (gonetworkmanager.Conne
var r0 gonetworkmanager.ConnectionSettings var r0 gonetworkmanager.ConnectionSettings
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(string) (gonetworkmanager.ConnectionSettings, error)); ok { if returnFunc, ok := ret.Get(0).(func(string) (gonetworkmanager.ConnectionSettings, error)); ok {
return rf(settingName) return returnFunc(settingName)
} }
if rf, ok := ret.Get(0).(func(string) gonetworkmanager.ConnectionSettings); ok { if returnFunc, ok := ret.Get(0).(func(string) gonetworkmanager.ConnectionSettings); ok {
r0 = rf(settingName) r0 = returnFunc(settingName)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.ConnectionSettings) r0 = ret.Get(0).(gonetworkmanager.ConnectionSettings)
} }
} }
if returnFunc, ok := ret.Get(1).(func(string) error); ok {
if rf, ok := ret.Get(1).(func(string) error); ok { r1 = returnFunc(settingName)
r1 = rf(settingName)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -359,30 +363,36 @@ type MockConnection_GetSecrets_Call struct {
// GetSecrets is a helper method to define mock.On call // GetSecrets is a helper method to define mock.On call
// - settingName string // - settingName string
func (_e *MockConnection_Expecter) GetSecrets(settingName interface{}) *MockConnection_GetSecrets_Call { func (_e *MockConnection_Expecter) GetSecrets(settingName any) *MockConnection_GetSecrets_Call {
return &MockConnection_GetSecrets_Call{Call: _e.mock.On("GetSecrets", settingName)} return &MockConnection_GetSecrets_Call{Call: _e.mock.On("GetSecrets", settingName)}
} }
func (_c *MockConnection_GetSecrets_Call) Run(run func(settingName string)) *MockConnection_GetSecrets_Call { func (_c *MockConnection_GetSecrets_Call) Run(run func(settingName string)) *MockConnection_GetSecrets_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockConnection_GetSecrets_Call) Return(_a0 gonetworkmanager.ConnectionSettings, _a1 error) *MockConnection_GetSecrets_Call { func (_c *MockConnection_GetSecrets_Call) Return(connectionSettings gonetworkmanager.ConnectionSettings, err error) *MockConnection_GetSecrets_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connectionSettings, err)
return _c return _c
} }
func (_c *MockConnection_GetSecrets_Call) RunAndReturn(run func(string) (gonetworkmanager.ConnectionSettings, error)) *MockConnection_GetSecrets_Call { func (_c *MockConnection_GetSecrets_Call) RunAndReturn(run func(settingName string) (gonetworkmanager.ConnectionSettings, error)) *MockConnection_GetSecrets_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// GetSettings provides a mock function with no fields // GetSettings provides a mock function for the type MockConnection
func (_m *MockConnection) GetSettings() (gonetworkmanager.ConnectionSettings, error) { func (_mock *MockConnection) GetSettings() (gonetworkmanager.ConnectionSettings, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetSettings") panic("no return value specified for GetSettings")
@@ -390,23 +400,21 @@ func (_m *MockConnection) GetSettings() (gonetworkmanager.ConnectionSettings, er
var r0 gonetworkmanager.ConnectionSettings var r0 gonetworkmanager.ConnectionSettings
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (gonetworkmanager.ConnectionSettings, error)); ok { if returnFunc, ok := ret.Get(0).(func() (gonetworkmanager.ConnectionSettings, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() gonetworkmanager.ConnectionSettings); ok { if returnFunc, ok := ret.Get(0).(func() gonetworkmanager.ConnectionSettings); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.ConnectionSettings) r0 = ret.Get(0).(gonetworkmanager.ConnectionSettings)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -427,8 +435,8 @@ func (_c *MockConnection_GetSettings_Call) Run(run func()) *MockConnection_GetSe
return _c return _c
} }
func (_c *MockConnection_GetSettings_Call) Return(_a0 gonetworkmanager.ConnectionSettings, _a1 error) *MockConnection_GetSettings_Call { func (_c *MockConnection_GetSettings_Call) Return(connectionSettings gonetworkmanager.ConnectionSettings, err error) *MockConnection_GetSettings_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connectionSettings, err)
return _c return _c
} }
@@ -437,9 +445,9 @@ func (_c *MockConnection_GetSettings_Call) RunAndReturn(run func() (gonetworkman
return _c return _c
} }
// MarshalJSON provides a mock function with no fields // MarshalJSON provides a mock function for the type MockConnection
func (_m *MockConnection) MarshalJSON() ([]byte, error) { func (_mock *MockConnection) MarshalJSON() ([]byte, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for MarshalJSON") panic("no return value specified for MarshalJSON")
@@ -447,23 +455,21 @@ func (_m *MockConnection) MarshalJSON() ([]byte, error) {
var r0 []byte var r0 []byte
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]byte, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]byte, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []byte); ok { if returnFunc, ok := ret.Get(0).(func() []byte); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte) r0 = ret.Get(0).([]byte)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -484,8 +490,8 @@ func (_c *MockConnection_MarshalJSON_Call) Run(run func()) *MockConnection_Marsh
return _c return _c
} }
func (_c *MockConnection_MarshalJSON_Call) Return(_a0 []byte, _a1 error) *MockConnection_MarshalJSON_Call { func (_c *MockConnection_MarshalJSON_Call) Return(bytes []byte, err error) *MockConnection_MarshalJSON_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(bytes, err)
return _c return _c
} }
@@ -494,21 +500,20 @@ func (_c *MockConnection_MarshalJSON_Call) RunAndReturn(run func() ([]byte, erro
return _c return _c
} }
// Save provides a mock function with no fields // Save provides a mock function for the type MockConnection
func (_m *MockConnection) Save() error { func (_mock *MockConnection) Save() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Save") panic("no return value specified for Save")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -529,8 +534,8 @@ func (_c *MockConnection_Save_Call) Run(run func()) *MockConnection_Save_Call {
return _c return _c
} }
func (_c *MockConnection_Save_Call) Return(_a0 error) *MockConnection_Save_Call { func (_c *MockConnection_Save_Call) Return(err error) *MockConnection_Save_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -539,21 +544,20 @@ func (_c *MockConnection_Save_Call) RunAndReturn(run func() error) *MockConnecti
return _c return _c
} }
// Update provides a mock function with given fields: settings // Update provides a mock function for the type MockConnection
func (_m *MockConnection) Update(settings gonetworkmanager.ConnectionSettings) error { func (_mock *MockConnection) Update(settings gonetworkmanager.ConnectionSettings) error {
ret := _m.Called(settings) ret := _mock.Called(settings)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Update") panic("no return value specified for Update")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) error); ok { if returnFunc, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) error); ok {
r0 = rf(settings) r0 = returnFunc(settings)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -564,42 +568,47 @@ type MockConnection_Update_Call struct {
// Update is a helper method to define mock.On call // Update is a helper method to define mock.On call
// - settings gonetworkmanager.ConnectionSettings // - settings gonetworkmanager.ConnectionSettings
func (_e *MockConnection_Expecter) Update(settings interface{}) *MockConnection_Update_Call { func (_e *MockConnection_Expecter) Update(settings any) *MockConnection_Update_Call {
return &MockConnection_Update_Call{Call: _e.mock.On("Update", settings)} return &MockConnection_Update_Call{Call: _e.mock.On("Update", settings)}
} }
func (_c *MockConnection_Update_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockConnection_Update_Call { func (_c *MockConnection_Update_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockConnection_Update_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(gonetworkmanager.ConnectionSettings)) var arg0 gonetworkmanager.ConnectionSettings
if args[0] != nil {
arg0 = args[0].(gonetworkmanager.ConnectionSettings)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockConnection_Update_Call) Return(_a0 error) *MockConnection_Update_Call { func (_c *MockConnection_Update_Call) Return(err error) *MockConnection_Update_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockConnection_Update_Call) RunAndReturn(run func(gonetworkmanager.ConnectionSettings) error) *MockConnection_Update_Call { func (_c *MockConnection_Update_Call) RunAndReturn(run func(settings gonetworkmanager.ConnectionSettings) error) *MockConnection_Update_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// UpdateUnsaved provides a mock function with given fields: settings // UpdateUnsaved provides a mock function for the type MockConnection
func (_m *MockConnection) UpdateUnsaved(settings gonetworkmanager.ConnectionSettings) error { func (_mock *MockConnection) UpdateUnsaved(settings gonetworkmanager.ConnectionSettings) error {
ret := _m.Called(settings) ret := _mock.Called(settings)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for UpdateUnsaved") panic("no return value specified for UpdateUnsaved")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) error); ok { if returnFunc, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) error); ok {
r0 = rf(settings) r0 = returnFunc(settings)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -610,37 +619,29 @@ type MockConnection_UpdateUnsaved_Call struct {
// UpdateUnsaved is a helper method to define mock.On call // UpdateUnsaved is a helper method to define mock.On call
// - settings gonetworkmanager.ConnectionSettings // - settings gonetworkmanager.ConnectionSettings
func (_e *MockConnection_Expecter) UpdateUnsaved(settings interface{}) *MockConnection_UpdateUnsaved_Call { func (_e *MockConnection_Expecter) UpdateUnsaved(settings any) *MockConnection_UpdateUnsaved_Call {
return &MockConnection_UpdateUnsaved_Call{Call: _e.mock.On("UpdateUnsaved", settings)} return &MockConnection_UpdateUnsaved_Call{Call: _e.mock.On("UpdateUnsaved", settings)}
} }
func (_c *MockConnection_UpdateUnsaved_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockConnection_UpdateUnsaved_Call { func (_c *MockConnection_UpdateUnsaved_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockConnection_UpdateUnsaved_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(gonetworkmanager.ConnectionSettings)) var arg0 gonetworkmanager.ConnectionSettings
if args[0] != nil {
arg0 = args[0].(gonetworkmanager.ConnectionSettings)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockConnection_UpdateUnsaved_Call) Return(_a0 error) *MockConnection_UpdateUnsaved_Call { func (_c *MockConnection_UpdateUnsaved_Call) Return(err error) *MockConnection_UpdateUnsaved_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockConnection_UpdateUnsaved_Call) RunAndReturn(run func(gonetworkmanager.ConnectionSettings) error) *MockConnection_UpdateUnsaved_Call { func (_c *MockConnection_UpdateUnsaved_Call) RunAndReturn(run func(settings gonetworkmanager.ConnectionSettings) error) *MockConnection_UpdateUnsaved_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockConnection creates a new instance of MockConnection. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockConnection(t interface {
mock.TestingT
Cleanup(func())
}) *MockConnection {
mock := &MockConnection{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package gonetworkmanager package gonetworkmanager
import ( import (
gonetworkmanager "github.com/Wifx/gonetworkmanager/v2" "github.com/Wifx/gonetworkmanager/v2"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockIP4Config creates a new instance of MockIP4Config. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockIP4Config(t interface {
mock.TestingT
Cleanup(func())
}) *MockIP4Config {
mock := &MockIP4Config{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockIP4Config is an autogenerated mock type for the IP4Config type // MockIP4Config is an autogenerated mock type for the IP4Config type
type MockIP4Config struct { type MockIP4Config struct {
mock.Mock mock.Mock
@@ -20,9 +36,9 @@ func (_m *MockIP4Config) EXPECT() *MockIP4Config_Expecter {
return &MockIP4Config_Expecter{mock: &_m.Mock} return &MockIP4Config_Expecter{mock: &_m.Mock}
} }
// GetPropertyAddressData provides a mock function with no fields // GetPropertyAddressData provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyAddressData() ([]gonetworkmanager.IP4AddressData, error) { func (_mock *MockIP4Config) GetPropertyAddressData() ([]gonetworkmanager.IP4AddressData, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyAddressData") panic("no return value specified for GetPropertyAddressData")
@@ -30,23 +46,21 @@ func (_m *MockIP4Config) GetPropertyAddressData() ([]gonetworkmanager.IP4Address
var r0 []gonetworkmanager.IP4AddressData var r0 []gonetworkmanager.IP4AddressData
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4AddressData, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4AddressData, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.IP4AddressData); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.IP4AddressData); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.IP4AddressData) r0 = ret.Get(0).([]gonetworkmanager.IP4AddressData)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -67,8 +81,8 @@ func (_c *MockIP4Config_GetPropertyAddressData_Call) Run(run func()) *MockIP4Con
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyAddressData_Call) Return(_a0 []gonetworkmanager.IP4AddressData, _a1 error) *MockIP4Config_GetPropertyAddressData_Call { func (_c *MockIP4Config_GetPropertyAddressData_Call) Return(iP4AddressDatas []gonetworkmanager.IP4AddressData, err error) *MockIP4Config_GetPropertyAddressData_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP4AddressDatas, err)
return _c return _c
} }
@@ -77,9 +91,9 @@ func (_c *MockIP4Config_GetPropertyAddressData_Call) RunAndReturn(run func() ([]
return _c return _c
} }
// GetPropertyAddresses provides a mock function with no fields // GetPropertyAddresses provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyAddresses() ([]gonetworkmanager.IP4Address, error) { func (_mock *MockIP4Config) GetPropertyAddresses() ([]gonetworkmanager.IP4Address, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyAddresses") panic("no return value specified for GetPropertyAddresses")
@@ -87,23 +101,21 @@ func (_m *MockIP4Config) GetPropertyAddresses() ([]gonetworkmanager.IP4Address,
var r0 []gonetworkmanager.IP4Address var r0 []gonetworkmanager.IP4Address
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4Address, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4Address, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.IP4Address); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.IP4Address); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.IP4Address) r0 = ret.Get(0).([]gonetworkmanager.IP4Address)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -124,8 +136,8 @@ func (_c *MockIP4Config_GetPropertyAddresses_Call) Run(run func()) *MockIP4Confi
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyAddresses_Call) Return(_a0 []gonetworkmanager.IP4Address, _a1 error) *MockIP4Config_GetPropertyAddresses_Call { func (_c *MockIP4Config_GetPropertyAddresses_Call) Return(iP4Addresss []gonetworkmanager.IP4Address, err error) *MockIP4Config_GetPropertyAddresses_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP4Addresss, err)
return _c return _c
} }
@@ -134,9 +146,9 @@ func (_c *MockIP4Config_GetPropertyAddresses_Call) RunAndReturn(run func() ([]go
return _c return _c
} }
// GetPropertyDnsOptions provides a mock function with no fields // GetPropertyDnsOptions provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyDnsOptions() ([]string, error) { func (_mock *MockIP4Config) GetPropertyDnsOptions() ([]string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDnsOptions") panic("no return value specified for GetPropertyDnsOptions")
@@ -144,23 +156,21 @@ func (_m *MockIP4Config) GetPropertyDnsOptions() ([]string, error) {
var r0 []string var r0 []string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]string, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []string); ok { if returnFunc, ok := ret.Get(0).(func() []string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]string) r0 = ret.Get(0).([]string)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -181,8 +191,8 @@ func (_c *MockIP4Config_GetPropertyDnsOptions_Call) Run(run func()) *MockIP4Conf
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyDnsOptions_Call) Return(_a0 []string, _a1 error) *MockIP4Config_GetPropertyDnsOptions_Call { func (_c *MockIP4Config_GetPropertyDnsOptions_Call) Return(strings []string, err error) *MockIP4Config_GetPropertyDnsOptions_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(strings, err)
return _c return _c
} }
@@ -191,9 +201,9 @@ func (_c *MockIP4Config_GetPropertyDnsOptions_Call) RunAndReturn(run func() ([]s
return _c return _c
} }
// GetPropertyDnsPriority provides a mock function with no fields // GetPropertyDnsPriority provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyDnsPriority() (uint32, error) { func (_mock *MockIP4Config) GetPropertyDnsPriority() (uint32, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDnsPriority") panic("no return value specified for GetPropertyDnsPriority")
@@ -201,21 +211,19 @@ func (_m *MockIP4Config) GetPropertyDnsPriority() (uint32, error) {
var r0 uint32 var r0 uint32
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (uint32, error)); ok { if returnFunc, ok := ret.Get(0).(func() (uint32, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() uint32); ok { if returnFunc, ok := ret.Get(0).(func() uint32); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(uint32) r0 = ret.Get(0).(uint32)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -236,8 +244,8 @@ func (_c *MockIP4Config_GetPropertyDnsPriority_Call) Run(run func()) *MockIP4Con
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyDnsPriority_Call) Return(_a0 uint32, _a1 error) *MockIP4Config_GetPropertyDnsPriority_Call { func (_c *MockIP4Config_GetPropertyDnsPriority_Call) Return(v uint32, err error) *MockIP4Config_GetPropertyDnsPriority_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(v, err)
return _c return _c
} }
@@ -246,9 +254,9 @@ func (_c *MockIP4Config_GetPropertyDnsPriority_Call) RunAndReturn(run func() (ui
return _c return _c
} }
// GetPropertyDomains provides a mock function with no fields // GetPropertyDomains provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyDomains() ([]string, error) { func (_mock *MockIP4Config) GetPropertyDomains() ([]string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyDomains") panic("no return value specified for GetPropertyDomains")
@@ -256,23 +264,21 @@ func (_m *MockIP4Config) GetPropertyDomains() ([]string, error) {
var r0 []string var r0 []string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]string, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []string); ok { if returnFunc, ok := ret.Get(0).(func() []string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]string) r0 = ret.Get(0).([]string)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -293,8 +299,8 @@ func (_c *MockIP4Config_GetPropertyDomains_Call) Run(run func()) *MockIP4Config_
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyDomains_Call) Return(_a0 []string, _a1 error) *MockIP4Config_GetPropertyDomains_Call { func (_c *MockIP4Config_GetPropertyDomains_Call) Return(strings []string, err error) *MockIP4Config_GetPropertyDomains_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(strings, err)
return _c return _c
} }
@@ -303,9 +309,9 @@ func (_c *MockIP4Config_GetPropertyDomains_Call) RunAndReturn(run func() ([]stri
return _c return _c
} }
// GetPropertyGateway provides a mock function with no fields // GetPropertyGateway provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyGateway() (string, error) { func (_mock *MockIP4Config) GetPropertyGateway() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyGateway") panic("no return value specified for GetPropertyGateway")
@@ -313,21 +319,19 @@ func (_m *MockIP4Config) GetPropertyGateway() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -348,8 +352,8 @@ func (_c *MockIP4Config_GetPropertyGateway_Call) Run(run func()) *MockIP4Config_
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyGateway_Call) Return(_a0 string, _a1 error) *MockIP4Config_GetPropertyGateway_Call { func (_c *MockIP4Config_GetPropertyGateway_Call) Return(s string, err error) *MockIP4Config_GetPropertyGateway_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -358,9 +362,9 @@ func (_c *MockIP4Config_GetPropertyGateway_Call) RunAndReturn(run func() (string
return _c return _c
} }
// GetPropertyNameserverData provides a mock function with no fields // GetPropertyNameserverData provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyNameserverData() ([]gonetworkmanager.IP4NameserverData, error) { func (_mock *MockIP4Config) GetPropertyNameserverData() ([]gonetworkmanager.IP4NameserverData, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyNameserverData") panic("no return value specified for GetPropertyNameserverData")
@@ -368,23 +372,21 @@ func (_m *MockIP4Config) GetPropertyNameserverData() ([]gonetworkmanager.IP4Name
var r0 []gonetworkmanager.IP4NameserverData var r0 []gonetworkmanager.IP4NameserverData
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4NameserverData, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4NameserverData, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.IP4NameserverData); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.IP4NameserverData); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.IP4NameserverData) r0 = ret.Get(0).([]gonetworkmanager.IP4NameserverData)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -405,8 +407,8 @@ func (_c *MockIP4Config_GetPropertyNameserverData_Call) Run(run func()) *MockIP4
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyNameserverData_Call) Return(_a0 []gonetworkmanager.IP4NameserverData, _a1 error) *MockIP4Config_GetPropertyNameserverData_Call { func (_c *MockIP4Config_GetPropertyNameserverData_Call) Return(iP4NameserverDatas []gonetworkmanager.IP4NameserverData, err error) *MockIP4Config_GetPropertyNameserverData_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP4NameserverDatas, err)
return _c return _c
} }
@@ -415,9 +417,9 @@ func (_c *MockIP4Config_GetPropertyNameserverData_Call) RunAndReturn(run func()
return _c return _c
} }
// GetPropertyNameservers provides a mock function with no fields // GetPropertyNameservers provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyNameservers() ([]string, error) { func (_mock *MockIP4Config) GetPropertyNameservers() ([]string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyNameservers") panic("no return value specified for GetPropertyNameservers")
@@ -425,23 +427,21 @@ func (_m *MockIP4Config) GetPropertyNameservers() ([]string, error) {
var r0 []string var r0 []string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]string, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []string); ok { if returnFunc, ok := ret.Get(0).(func() []string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]string) r0 = ret.Get(0).([]string)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -462,8 +462,8 @@ func (_c *MockIP4Config_GetPropertyNameservers_Call) Run(run func()) *MockIP4Con
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyNameservers_Call) Return(_a0 []string, _a1 error) *MockIP4Config_GetPropertyNameservers_Call { func (_c *MockIP4Config_GetPropertyNameservers_Call) Return(strings []string, err error) *MockIP4Config_GetPropertyNameservers_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(strings, err)
return _c return _c
} }
@@ -472,9 +472,9 @@ func (_c *MockIP4Config_GetPropertyNameservers_Call) RunAndReturn(run func() ([]
return _c return _c
} }
// GetPropertyRouteData provides a mock function with no fields // GetPropertyRouteData provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyRouteData() ([]gonetworkmanager.IP4RouteData, error) { func (_mock *MockIP4Config) GetPropertyRouteData() ([]gonetworkmanager.IP4RouteData, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyRouteData") panic("no return value specified for GetPropertyRouteData")
@@ -482,23 +482,21 @@ func (_m *MockIP4Config) GetPropertyRouteData() ([]gonetworkmanager.IP4RouteData
var r0 []gonetworkmanager.IP4RouteData var r0 []gonetworkmanager.IP4RouteData
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4RouteData, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4RouteData, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.IP4RouteData); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.IP4RouteData); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.IP4RouteData) r0 = ret.Get(0).([]gonetworkmanager.IP4RouteData)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -519,8 +517,8 @@ func (_c *MockIP4Config_GetPropertyRouteData_Call) Run(run func()) *MockIP4Confi
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyRouteData_Call) Return(_a0 []gonetworkmanager.IP4RouteData, _a1 error) *MockIP4Config_GetPropertyRouteData_Call { func (_c *MockIP4Config_GetPropertyRouteData_Call) Return(iP4RouteDatas []gonetworkmanager.IP4RouteData, err error) *MockIP4Config_GetPropertyRouteData_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP4RouteDatas, err)
return _c return _c
} }
@@ -529,9 +527,9 @@ func (_c *MockIP4Config_GetPropertyRouteData_Call) RunAndReturn(run func() ([]go
return _c return _c
} }
// GetPropertyRoutes provides a mock function with no fields // GetPropertyRoutes provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyRoutes() ([]gonetworkmanager.IP4Route, error) { func (_mock *MockIP4Config) GetPropertyRoutes() ([]gonetworkmanager.IP4Route, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyRoutes") panic("no return value specified for GetPropertyRoutes")
@@ -539,23 +537,21 @@ func (_m *MockIP4Config) GetPropertyRoutes() ([]gonetworkmanager.IP4Route, error
var r0 []gonetworkmanager.IP4Route var r0 []gonetworkmanager.IP4Route
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4Route, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.IP4Route, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.IP4Route); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.IP4Route); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.IP4Route) r0 = ret.Get(0).([]gonetworkmanager.IP4Route)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -576,8 +572,8 @@ func (_c *MockIP4Config_GetPropertyRoutes_Call) Run(run func()) *MockIP4Config_G
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyRoutes_Call) Return(_a0 []gonetworkmanager.IP4Route, _a1 error) *MockIP4Config_GetPropertyRoutes_Call { func (_c *MockIP4Config_GetPropertyRoutes_Call) Return(iP4Routes []gonetworkmanager.IP4Route, err error) *MockIP4Config_GetPropertyRoutes_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(iP4Routes, err)
return _c return _c
} }
@@ -586,9 +582,9 @@ func (_c *MockIP4Config_GetPropertyRoutes_Call) RunAndReturn(run func() ([]gonet
return _c return _c
} }
// GetPropertySearches provides a mock function with no fields // GetPropertySearches provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertySearches() ([]string, error) { func (_mock *MockIP4Config) GetPropertySearches() ([]string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertySearches") panic("no return value specified for GetPropertySearches")
@@ -596,23 +592,21 @@ func (_m *MockIP4Config) GetPropertySearches() ([]string, error) {
var r0 []string var r0 []string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]string, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []string); ok { if returnFunc, ok := ret.Get(0).(func() []string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]string) r0 = ret.Get(0).([]string)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -633,8 +627,8 @@ func (_c *MockIP4Config_GetPropertySearches_Call) Run(run func()) *MockIP4Config
return _c return _c
} }
func (_c *MockIP4Config_GetPropertySearches_Call) Return(_a0 []string, _a1 error) *MockIP4Config_GetPropertySearches_Call { func (_c *MockIP4Config_GetPropertySearches_Call) Return(strings []string, err error) *MockIP4Config_GetPropertySearches_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(strings, err)
return _c return _c
} }
@@ -643,9 +637,9 @@ func (_c *MockIP4Config_GetPropertySearches_Call) RunAndReturn(run func() ([]str
return _c return _c
} }
// GetPropertyWinsServerData provides a mock function with no fields // GetPropertyWinsServerData provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) GetPropertyWinsServerData() ([]string, error) { func (_mock *MockIP4Config) GetPropertyWinsServerData() ([]string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyWinsServerData") panic("no return value specified for GetPropertyWinsServerData")
@@ -653,23 +647,21 @@ func (_m *MockIP4Config) GetPropertyWinsServerData() ([]string, error) {
var r0 []string var r0 []string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]string, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []string); ok { if returnFunc, ok := ret.Get(0).(func() []string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]string) r0 = ret.Get(0).([]string)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -690,8 +682,8 @@ func (_c *MockIP4Config_GetPropertyWinsServerData_Call) Run(run func()) *MockIP4
return _c return _c
} }
func (_c *MockIP4Config_GetPropertyWinsServerData_Call) Return(_a0 []string, _a1 error) *MockIP4Config_GetPropertyWinsServerData_Call { func (_c *MockIP4Config_GetPropertyWinsServerData_Call) Return(strings []string, err error) *MockIP4Config_GetPropertyWinsServerData_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(strings, err)
return _c return _c
} }
@@ -700,9 +692,9 @@ func (_c *MockIP4Config_GetPropertyWinsServerData_Call) RunAndReturn(run func()
return _c return _c
} }
// MarshalJSON provides a mock function with no fields // MarshalJSON provides a mock function for the type MockIP4Config
func (_m *MockIP4Config) MarshalJSON() ([]byte, error) { func (_mock *MockIP4Config) MarshalJSON() ([]byte, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for MarshalJSON") panic("no return value specified for MarshalJSON")
@@ -710,23 +702,21 @@ func (_m *MockIP4Config) MarshalJSON() ([]byte, error) {
var r0 []byte var r0 []byte
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]byte, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]byte, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []byte); ok { if returnFunc, ok := ret.Get(0).(func() []byte); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte) r0 = ret.Get(0).([]byte)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -747,8 +737,8 @@ func (_c *MockIP4Config_MarshalJSON_Call) Run(run func()) *MockIP4Config_Marshal
return _c return _c
} }
func (_c *MockIP4Config_MarshalJSON_Call) Return(_a0 []byte, _a1 error) *MockIP4Config_MarshalJSON_Call { func (_c *MockIP4Config_MarshalJSON_Call) Return(bytes []byte, err error) *MockIP4Config_MarshalJSON_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(bytes, err)
return _c return _c
} }
@@ -756,17 +746,3 @@ func (_c *MockIP4Config_MarshalJSON_Call) RunAndReturn(run func() ([]byte, error
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockIP4Config creates a new instance of MockIP4Config. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockIP4Config(t interface {
mock.TestingT
Cleanup(func())
}) *MockIP4Config {
mock := &MockIP4Config{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package gonetworkmanager package gonetworkmanager
import ( import (
gonetworkmanager "github.com/Wifx/gonetworkmanager/v2" "github.com/Wifx/gonetworkmanager/v2"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockSettings creates a new instance of MockSettings. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockSettings(t interface {
mock.TestingT
Cleanup(func())
}) *MockSettings {
mock := &MockSettings{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockSettings is an autogenerated mock type for the Settings type // MockSettings is an autogenerated mock type for the Settings type
type MockSettings struct { type MockSettings struct {
mock.Mock mock.Mock
@@ -20,9 +36,9 @@ func (_m *MockSettings) EXPECT() *MockSettings_Expecter {
return &MockSettings_Expecter{mock: &_m.Mock} return &MockSettings_Expecter{mock: &_m.Mock}
} }
// AddConnection provides a mock function with given fields: settings // AddConnection provides a mock function for the type MockSettings
func (_m *MockSettings) AddConnection(settings gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error) { func (_mock *MockSettings) AddConnection(settings gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error) {
ret := _m.Called(settings) ret := _mock.Called(settings)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for AddConnection") panic("no return value specified for AddConnection")
@@ -30,23 +46,21 @@ func (_m *MockSettings) AddConnection(settings gonetworkmanager.ConnectionSettin
var r0 gonetworkmanager.Connection var r0 gonetworkmanager.Connection
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)); ok { if returnFunc, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)); ok {
return rf(settings) return returnFunc(settings)
} }
if rf, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) gonetworkmanager.Connection); ok { if returnFunc, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) gonetworkmanager.Connection); ok {
r0 = rf(settings) r0 = returnFunc(settings)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.Connection) r0 = ret.Get(0).(gonetworkmanager.Connection)
} }
} }
if returnFunc, ok := ret.Get(1).(func(gonetworkmanager.ConnectionSettings) error); ok {
if rf, ok := ret.Get(1).(func(gonetworkmanager.ConnectionSettings) error); ok { r1 = returnFunc(settings)
r1 = rf(settings)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -57,30 +71,36 @@ type MockSettings_AddConnection_Call struct {
// AddConnection is a helper method to define mock.On call // AddConnection is a helper method to define mock.On call
// - settings gonetworkmanager.ConnectionSettings // - settings gonetworkmanager.ConnectionSettings
func (_e *MockSettings_Expecter) AddConnection(settings interface{}) *MockSettings_AddConnection_Call { func (_e *MockSettings_Expecter) AddConnection(settings any) *MockSettings_AddConnection_Call {
return &MockSettings_AddConnection_Call{Call: _e.mock.On("AddConnection", settings)} return &MockSettings_AddConnection_Call{Call: _e.mock.On("AddConnection", settings)}
} }
func (_c *MockSettings_AddConnection_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockSettings_AddConnection_Call { func (_c *MockSettings_AddConnection_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockSettings_AddConnection_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(gonetworkmanager.ConnectionSettings)) var arg0 gonetworkmanager.ConnectionSettings
if args[0] != nil {
arg0 = args[0].(gonetworkmanager.ConnectionSettings)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockSettings_AddConnection_Call) Return(_a0 gonetworkmanager.Connection, _a1 error) *MockSettings_AddConnection_Call { func (_c *MockSettings_AddConnection_Call) Return(connection gonetworkmanager.Connection, err error) *MockSettings_AddConnection_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connection, err)
return _c return _c
} }
func (_c *MockSettings_AddConnection_Call) RunAndReturn(run func(gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)) *MockSettings_AddConnection_Call { func (_c *MockSettings_AddConnection_Call) RunAndReturn(run func(settings gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)) *MockSettings_AddConnection_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// AddConnectionUnsaved provides a mock function with given fields: settings // AddConnectionUnsaved provides a mock function for the type MockSettings
func (_m *MockSettings) AddConnectionUnsaved(settings gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error) { func (_mock *MockSettings) AddConnectionUnsaved(settings gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error) {
ret := _m.Called(settings) ret := _mock.Called(settings)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for AddConnectionUnsaved") panic("no return value specified for AddConnectionUnsaved")
@@ -88,23 +108,21 @@ func (_m *MockSettings) AddConnectionUnsaved(settings gonetworkmanager.Connectio
var r0 gonetworkmanager.Connection var r0 gonetworkmanager.Connection
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)); ok { if returnFunc, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)); ok {
return rf(settings) return returnFunc(settings)
} }
if rf, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) gonetworkmanager.Connection); ok { if returnFunc, ok := ret.Get(0).(func(gonetworkmanager.ConnectionSettings) gonetworkmanager.Connection); ok {
r0 = rf(settings) r0 = returnFunc(settings)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.Connection) r0 = ret.Get(0).(gonetworkmanager.Connection)
} }
} }
if returnFunc, ok := ret.Get(1).(func(gonetworkmanager.ConnectionSettings) error); ok {
if rf, ok := ret.Get(1).(func(gonetworkmanager.ConnectionSettings) error); ok { r1 = returnFunc(settings)
r1 = rf(settings)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -115,30 +133,36 @@ type MockSettings_AddConnectionUnsaved_Call struct {
// AddConnectionUnsaved is a helper method to define mock.On call // AddConnectionUnsaved is a helper method to define mock.On call
// - settings gonetworkmanager.ConnectionSettings // - settings gonetworkmanager.ConnectionSettings
func (_e *MockSettings_Expecter) AddConnectionUnsaved(settings interface{}) *MockSettings_AddConnectionUnsaved_Call { func (_e *MockSettings_Expecter) AddConnectionUnsaved(settings any) *MockSettings_AddConnectionUnsaved_Call {
return &MockSettings_AddConnectionUnsaved_Call{Call: _e.mock.On("AddConnectionUnsaved", settings)} return &MockSettings_AddConnectionUnsaved_Call{Call: _e.mock.On("AddConnectionUnsaved", settings)}
} }
func (_c *MockSettings_AddConnectionUnsaved_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockSettings_AddConnectionUnsaved_Call { func (_c *MockSettings_AddConnectionUnsaved_Call) Run(run func(settings gonetworkmanager.ConnectionSettings)) *MockSettings_AddConnectionUnsaved_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(gonetworkmanager.ConnectionSettings)) var arg0 gonetworkmanager.ConnectionSettings
if args[0] != nil {
arg0 = args[0].(gonetworkmanager.ConnectionSettings)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockSettings_AddConnectionUnsaved_Call) Return(_a0 gonetworkmanager.Connection, _a1 error) *MockSettings_AddConnectionUnsaved_Call { func (_c *MockSettings_AddConnectionUnsaved_Call) Return(connection gonetworkmanager.Connection, err error) *MockSettings_AddConnectionUnsaved_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connection, err)
return _c return _c
} }
func (_c *MockSettings_AddConnectionUnsaved_Call) RunAndReturn(run func(gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)) *MockSettings_AddConnectionUnsaved_Call { func (_c *MockSettings_AddConnectionUnsaved_Call) RunAndReturn(run func(settings gonetworkmanager.ConnectionSettings) (gonetworkmanager.Connection, error)) *MockSettings_AddConnectionUnsaved_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// GetConnectionByUUID provides a mock function with given fields: uuid // GetConnectionByUUID provides a mock function for the type MockSettings
func (_m *MockSettings) GetConnectionByUUID(uuid string) (gonetworkmanager.Connection, error) { func (_mock *MockSettings) GetConnectionByUUID(uuid string) (gonetworkmanager.Connection, error) {
ret := _m.Called(uuid) ret := _mock.Called(uuid)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetConnectionByUUID") panic("no return value specified for GetConnectionByUUID")
@@ -146,23 +170,21 @@ func (_m *MockSettings) GetConnectionByUUID(uuid string) (gonetworkmanager.Conne
var r0 gonetworkmanager.Connection var r0 gonetworkmanager.Connection
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(string) (gonetworkmanager.Connection, error)); ok { if returnFunc, ok := ret.Get(0).(func(string) (gonetworkmanager.Connection, error)); ok {
return rf(uuid) return returnFunc(uuid)
} }
if rf, ok := ret.Get(0).(func(string) gonetworkmanager.Connection); ok { if returnFunc, ok := ret.Get(0).(func(string) gonetworkmanager.Connection); ok {
r0 = rf(uuid) r0 = returnFunc(uuid)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(gonetworkmanager.Connection) r0 = ret.Get(0).(gonetworkmanager.Connection)
} }
} }
if returnFunc, ok := ret.Get(1).(func(string) error); ok {
if rf, ok := ret.Get(1).(func(string) error); ok { r1 = returnFunc(uuid)
r1 = rf(uuid)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -173,30 +195,36 @@ type MockSettings_GetConnectionByUUID_Call struct {
// GetConnectionByUUID is a helper method to define mock.On call // GetConnectionByUUID is a helper method to define mock.On call
// - uuid string // - uuid string
func (_e *MockSettings_Expecter) GetConnectionByUUID(uuid interface{}) *MockSettings_GetConnectionByUUID_Call { func (_e *MockSettings_Expecter) GetConnectionByUUID(uuid any) *MockSettings_GetConnectionByUUID_Call {
return &MockSettings_GetConnectionByUUID_Call{Call: _e.mock.On("GetConnectionByUUID", uuid)} return &MockSettings_GetConnectionByUUID_Call{Call: _e.mock.On("GetConnectionByUUID", uuid)}
} }
func (_c *MockSettings_GetConnectionByUUID_Call) Run(run func(uuid string)) *MockSettings_GetConnectionByUUID_Call { func (_c *MockSettings_GetConnectionByUUID_Call) Run(run func(uuid string)) *MockSettings_GetConnectionByUUID_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockSettings_GetConnectionByUUID_Call) Return(_a0 gonetworkmanager.Connection, _a1 error) *MockSettings_GetConnectionByUUID_Call { func (_c *MockSettings_GetConnectionByUUID_Call) Return(connection gonetworkmanager.Connection, err error) *MockSettings_GetConnectionByUUID_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connection, err)
return _c return _c
} }
func (_c *MockSettings_GetConnectionByUUID_Call) RunAndReturn(run func(string) (gonetworkmanager.Connection, error)) *MockSettings_GetConnectionByUUID_Call { func (_c *MockSettings_GetConnectionByUUID_Call) RunAndReturn(run func(uuid string) (gonetworkmanager.Connection, error)) *MockSettings_GetConnectionByUUID_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// GetPropertyCanModify provides a mock function with no fields // GetPropertyCanModify provides a mock function for the type MockSettings
func (_m *MockSettings) GetPropertyCanModify() (bool, error) { func (_mock *MockSettings) GetPropertyCanModify() (bool, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyCanModify") panic("no return value specified for GetPropertyCanModify")
@@ -204,21 +232,19 @@ func (_m *MockSettings) GetPropertyCanModify() (bool, error) {
var r0 bool var r0 bool
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (bool, error)); ok { if returnFunc, ok := ret.Get(0).(func() (bool, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() bool); ok { if returnFunc, ok := ret.Get(0).(func() bool); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(bool) r0 = ret.Get(0).(bool)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -239,8 +265,8 @@ func (_c *MockSettings_GetPropertyCanModify_Call) Run(run func()) *MockSettings_
return _c return _c
} }
func (_c *MockSettings_GetPropertyCanModify_Call) Return(_a0 bool, _a1 error) *MockSettings_GetPropertyCanModify_Call { func (_c *MockSettings_GetPropertyCanModify_Call) Return(b bool, err error) *MockSettings_GetPropertyCanModify_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(b, err)
return _c return _c
} }
@@ -249,9 +275,9 @@ func (_c *MockSettings_GetPropertyCanModify_Call) RunAndReturn(run func() (bool,
return _c return _c
} }
// GetPropertyHostname provides a mock function with no fields // GetPropertyHostname provides a mock function for the type MockSettings
func (_m *MockSettings) GetPropertyHostname() (string, error) { func (_mock *MockSettings) GetPropertyHostname() (string, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetPropertyHostname") panic("no return value specified for GetPropertyHostname")
@@ -259,21 +285,19 @@ func (_m *MockSettings) GetPropertyHostname() (string, error) {
var r0 string var r0 string
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok { if returnFunc, ok := ret.Get(0).(func() (string, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -294,8 +318,8 @@ func (_c *MockSettings_GetPropertyHostname_Call) Run(run func()) *MockSettings_G
return _c return _c
} }
func (_c *MockSettings_GetPropertyHostname_Call) Return(_a0 string, _a1 error) *MockSettings_GetPropertyHostname_Call { func (_c *MockSettings_GetPropertyHostname_Call) Return(s string, err error) *MockSettings_GetPropertyHostname_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(s, err)
return _c return _c
} }
@@ -304,9 +328,9 @@ func (_c *MockSettings_GetPropertyHostname_Call) RunAndReturn(run func() (string
return _c return _c
} }
// ListConnections provides a mock function with no fields // ListConnections provides a mock function for the type MockSettings
func (_m *MockSettings) ListConnections() ([]gonetworkmanager.Connection, error) { func (_mock *MockSettings) ListConnections() ([]gonetworkmanager.Connection, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for ListConnections") panic("no return value specified for ListConnections")
@@ -314,23 +338,21 @@ func (_m *MockSettings) ListConnections() ([]gonetworkmanager.Connection, error)
var r0 []gonetworkmanager.Connection var r0 []gonetworkmanager.Connection
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() ([]gonetworkmanager.Connection, error)); ok { if returnFunc, ok := ret.Get(0).(func() ([]gonetworkmanager.Connection, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() []gonetworkmanager.Connection); ok { if returnFunc, ok := ret.Get(0).(func() []gonetworkmanager.Connection); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).([]gonetworkmanager.Connection) r0 = ret.Get(0).([]gonetworkmanager.Connection)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -351,8 +373,8 @@ func (_c *MockSettings_ListConnections_Call) Run(run func()) *MockSettings_ListC
return _c return _c
} }
func (_c *MockSettings_ListConnections_Call) Return(_a0 []gonetworkmanager.Connection, _a1 error) *MockSettings_ListConnections_Call { func (_c *MockSettings_ListConnections_Call) Return(connections []gonetworkmanager.Connection, err error) *MockSettings_ListConnections_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(connections, err)
return _c return _c
} }
@@ -361,21 +383,20 @@ func (_c *MockSettings_ListConnections_Call) RunAndReturn(run func() ([]gonetwor
return _c return _c
} }
// ReloadConnections provides a mock function with no fields // ReloadConnections provides a mock function for the type MockSettings
func (_m *MockSettings) ReloadConnections() error { func (_mock *MockSettings) ReloadConnections() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for ReloadConnections") panic("no return value specified for ReloadConnections")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -396,8 +417,8 @@ func (_c *MockSettings_ReloadConnections_Call) Run(run func()) *MockSettings_Rel
return _c return _c
} }
func (_c *MockSettings_ReloadConnections_Call) Return(_a0 error) *MockSettings_ReloadConnections_Call { func (_c *MockSettings_ReloadConnections_Call) Return(err error) *MockSettings_ReloadConnections_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -406,21 +427,20 @@ func (_c *MockSettings_ReloadConnections_Call) RunAndReturn(run func() error) *M
return _c return _c
} }
// SaveHostname provides a mock function with given fields: hostname // SaveHostname provides a mock function for the type MockSettings
func (_m *MockSettings) SaveHostname(hostname string) error { func (_mock *MockSettings) SaveHostname(hostname string) error {
ret := _m.Called(hostname) ret := _mock.Called(hostname)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for SaveHostname") panic("no return value specified for SaveHostname")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok { if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(hostname) r0 = returnFunc(hostname)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -431,37 +451,29 @@ type MockSettings_SaveHostname_Call struct {
// SaveHostname is a helper method to define mock.On call // SaveHostname is a helper method to define mock.On call
// - hostname string // - hostname string
func (_e *MockSettings_Expecter) SaveHostname(hostname interface{}) *MockSettings_SaveHostname_Call { func (_e *MockSettings_Expecter) SaveHostname(hostname any) *MockSettings_SaveHostname_Call {
return &MockSettings_SaveHostname_Call{Call: _e.mock.On("SaveHostname", hostname)} return &MockSettings_SaveHostname_Call{Call: _e.mock.On("SaveHostname", hostname)}
} }
func (_c *MockSettings_SaveHostname_Call) Run(run func(hostname string)) *MockSettings_SaveHostname_Call { func (_c *MockSettings_SaveHostname_Call) Run(run func(hostname string)) *MockSettings_SaveHostname_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockSettings_SaveHostname_Call) Return(_a0 error) *MockSettings_SaveHostname_Call { func (_c *MockSettings_SaveHostname_Call) Return(err error) *MockSettings_SaveHostname_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockSettings_SaveHostname_Call) RunAndReturn(run func(string) error) *MockSettings_SaveHostname_Call { func (_c *MockSettings_SaveHostname_Call) RunAndReturn(run func(hostname string) error) *MockSettings_SaveHostname_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockSettings creates a new instance of MockSettings. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockSettings(t interface {
mock.TestingT
Cleanup(func())
}) *MockSettings {
mock := &MockSettings{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -1,14 +1,30 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package dbus package dbus
import ( import (
context "context" "context"
dbus "github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockBusObject creates a new instance of MockBusObject. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockBusObject(t interface {
mock.TestingT
Cleanup(func())
}) *MockBusObject {
mock := &MockBusObject{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockBusObject is an autogenerated mock type for the BusObject type // MockBusObject is an autogenerated mock type for the BusObject type
type MockBusObject struct { type MockBusObject struct {
mock.Mock mock.Mock
@@ -22,30 +38,30 @@ func (_m *MockBusObject) EXPECT() *MockBusObject_Expecter {
return &MockBusObject_Expecter{mock: &_m.Mock} return &MockBusObject_Expecter{mock: &_m.Mock}
} }
// AddMatchSignal provides a mock function with given fields: iface, member, options // AddMatchSignal provides a mock function for the type MockBusObject
func (_m *MockBusObject) AddMatchSignal(iface string, member string, options ...dbus.MatchOption) *dbus.Call { func (_mock *MockBusObject) AddMatchSignal(iface string, member string, options ...dbus.MatchOption) *dbus.Call {
_va := make([]interface{}, len(options)) // dbus.MatchOption
_va := make([]any, len(options))
for _i := range options { for _i := range options {
_va[_i] = options[_i] _va[_i] = options[_i]
} }
var _ca []interface{} var _ca []any
_ca = append(_ca, iface, member) _ca = append(_ca, iface, member)
_ca = append(_ca, _va...) _ca = append(_ca, _va...)
ret := _m.Called(_ca...) ret := _mock.Called(_ca...)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for AddMatchSignal") panic("no return value specified for AddMatchSignal")
} }
var r0 *dbus.Call var r0 *dbus.Call
if rf, ok := ret.Get(0).(func(string, string, ...dbus.MatchOption) *dbus.Call); ok { if returnFunc, ok := ret.Get(0).(func(string, string, ...dbus.MatchOption) *dbus.Call); ok {
r0 = rf(iface, member, options...) r0 = returnFunc(iface, member, options...)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*dbus.Call) r0 = ret.Get(0).(*dbus.Call)
} }
} }
return r0 return r0
} }
@@ -58,54 +74,67 @@ type MockBusObject_AddMatchSignal_Call struct {
// - iface string // - iface string
// - member string // - member string
// - options ...dbus.MatchOption // - options ...dbus.MatchOption
func (_e *MockBusObject_Expecter) AddMatchSignal(iface interface{}, member interface{}, options ...interface{}) *MockBusObject_AddMatchSignal_Call { func (_e *MockBusObject_Expecter) AddMatchSignal(iface any, member any, options ...any) *MockBusObject_AddMatchSignal_Call {
return &MockBusObject_AddMatchSignal_Call{Call: _e.mock.On("AddMatchSignal", return &MockBusObject_AddMatchSignal_Call{Call: _e.mock.On("AddMatchSignal",
append([]interface{}{iface, member}, options...)...)} append([]any{iface, member}, options...)...)}
} }
func (_c *MockBusObject_AddMatchSignal_Call) Run(run func(iface string, member string, options ...dbus.MatchOption)) *MockBusObject_AddMatchSignal_Call { func (_c *MockBusObject_AddMatchSignal_Call) Run(run func(iface string, member string, options ...dbus.MatchOption)) *MockBusObject_AddMatchSignal_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 []dbus.MatchOption
variadicArgs := make([]dbus.MatchOption, len(args)-2) variadicArgs := make([]dbus.MatchOption, len(args)-2)
for i, a := range args[2:] { for i, a := range args[2:] {
if a != nil { if a != nil {
variadicArgs[i] = a.(dbus.MatchOption) variadicArgs[i] = a.(dbus.MatchOption)
} }
} }
run(args[0].(string), args[1].(string), variadicArgs...) arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_AddMatchSignal_Call) Return(_a0 *dbus.Call) *MockBusObject_AddMatchSignal_Call { func (_c *MockBusObject_AddMatchSignal_Call) Return(call *dbus.Call) *MockBusObject_AddMatchSignal_Call {
_c.Call.Return(_a0) _c.Call.Return(call)
return _c return _c
} }
func (_c *MockBusObject_AddMatchSignal_Call) RunAndReturn(run func(string, string, ...dbus.MatchOption) *dbus.Call) *MockBusObject_AddMatchSignal_Call { func (_c *MockBusObject_AddMatchSignal_Call) RunAndReturn(run func(iface string, member string, options ...dbus.MatchOption) *dbus.Call) *MockBusObject_AddMatchSignal_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Call provides a mock function with given fields: method, flags, args // Call provides a mock function for the type MockBusObject
func (_m *MockBusObject) Call(method string, flags dbus.Flags, args ...interface{}) *dbus.Call { func (_mock *MockBusObject) Call(method string, flags dbus.Flags, args ...any) *dbus.Call {
var _ca []interface{} var _ca []any
_ca = append(_ca, method, flags) _ca = append(_ca, method, flags)
_ca = append(_ca, args...) _ca = append(_ca, args...)
ret := _m.Called(_ca...) ret := _mock.Called(_ca...)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Call") panic("no return value specified for Call")
} }
var r0 *dbus.Call var r0 *dbus.Call
if rf, ok := ret.Get(0).(func(string, dbus.Flags, ...interface{}) *dbus.Call); ok { if returnFunc, ok := ret.Get(0).(func(string, dbus.Flags, ...any) *dbus.Call); ok {
r0 = rf(method, flags, args...) r0 = returnFunc(method, flags, args...)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*dbus.Call) r0 = ret.Get(0).(*dbus.Call)
} }
} }
return r0 return r0
} }
@@ -117,55 +146,68 @@ type MockBusObject_Call_Call struct {
// Call is a helper method to define mock.On call // Call is a helper method to define mock.On call
// - method string // - method string
// - flags dbus.Flags // - flags dbus.Flags
// - args ...interface{} // - args ...any
func (_e *MockBusObject_Expecter) Call(method interface{}, flags interface{}, args ...interface{}) *MockBusObject_Call_Call { func (_e *MockBusObject_Expecter) Call(method any, flags any, args ...any) *MockBusObject_Call_Call {
return &MockBusObject_Call_Call{Call: _e.mock.On("Call", return &MockBusObject_Call_Call{Call: _e.mock.On("Call",
append([]interface{}{method, flags}, args...)...)} append([]any{method, flags}, args...)...)}
} }
func (_c *MockBusObject_Call_Call) Run(run func(method string, flags dbus.Flags, args ...interface{})) *MockBusObject_Call_Call { func (_c *MockBusObject_Call_Call) Run(run func(method string, flags dbus.Flags, args ...any)) *MockBusObject_Call_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 dbus.Flags
if args[1] != nil {
arg1 = args[1].(dbus.Flags)
}
var arg2 []any
variadicArgs := make([]any, len(args)-2)
for i, a := range args[2:] { for i, a := range args[2:] {
if a != nil { if a != nil {
variadicArgs[i] = a.(interface{}) variadicArgs[i] = a.(any)
} }
} }
run(args[0].(string), args[1].(dbus.Flags), variadicArgs...) arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_Call_Call) Return(_a0 *dbus.Call) *MockBusObject_Call_Call { func (_c *MockBusObject_Call_Call) Return(call *dbus.Call) *MockBusObject_Call_Call {
_c.Call.Return(_a0) _c.Call.Return(call)
return _c return _c
} }
func (_c *MockBusObject_Call_Call) RunAndReturn(run func(string, dbus.Flags, ...interface{}) *dbus.Call) *MockBusObject_Call_Call { func (_c *MockBusObject_Call_Call) RunAndReturn(run func(method string, flags dbus.Flags, args ...any) *dbus.Call) *MockBusObject_Call_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// CallWithContext provides a mock function with given fields: ctx, method, flags, args // CallWithContext provides a mock function for the type MockBusObject
func (_m *MockBusObject) CallWithContext(ctx context.Context, method string, flags dbus.Flags, args ...interface{}) *dbus.Call { func (_mock *MockBusObject) CallWithContext(ctx context.Context, method string, flags dbus.Flags, args ...any) *dbus.Call {
var _ca []interface{} var _ca []any
_ca = append(_ca, ctx, method, flags) _ca = append(_ca, ctx, method, flags)
_ca = append(_ca, args...) _ca = append(_ca, args...)
ret := _m.Called(_ca...) ret := _mock.Called(_ca...)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for CallWithContext") panic("no return value specified for CallWithContext")
} }
var r0 *dbus.Call var r0 *dbus.Call
if rf, ok := ret.Get(0).(func(context.Context, string, dbus.Flags, ...interface{}) *dbus.Call); ok { if returnFunc, ok := ret.Get(0).(func(context.Context, string, dbus.Flags, ...any) *dbus.Call); ok {
r0 = rf(ctx, method, flags, args...) r0 = returnFunc(ctx, method, flags, args...)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*dbus.Call) r0 = ret.Get(0).(*dbus.Call)
} }
} }
return r0 return r0
} }
@@ -178,50 +220,68 @@ type MockBusObject_CallWithContext_Call struct {
// - ctx context.Context // - ctx context.Context
// - method string // - method string
// - flags dbus.Flags // - flags dbus.Flags
// - args ...interface{} // - args ...any
func (_e *MockBusObject_Expecter) CallWithContext(ctx interface{}, method interface{}, flags interface{}, args ...interface{}) *MockBusObject_CallWithContext_Call { func (_e *MockBusObject_Expecter) CallWithContext(ctx any, method any, flags any, args ...any) *MockBusObject_CallWithContext_Call {
return &MockBusObject_CallWithContext_Call{Call: _e.mock.On("CallWithContext", return &MockBusObject_CallWithContext_Call{Call: _e.mock.On("CallWithContext",
append([]interface{}{ctx, method, flags}, args...)...)} append([]any{ctx, method, flags}, args...)...)}
} }
func (_c *MockBusObject_CallWithContext_Call) Run(run func(ctx context.Context, method string, flags dbus.Flags, args ...interface{})) *MockBusObject_CallWithContext_Call { func (_c *MockBusObject_CallWithContext_Call) Run(run func(ctx context.Context, method string, flags dbus.Flags, args ...any)) *MockBusObject_CallWithContext_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-3) var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 dbus.Flags
if args[2] != nil {
arg2 = args[2].(dbus.Flags)
}
var arg3 []any
variadicArgs := make([]any, len(args)-3)
for i, a := range args[3:] { for i, a := range args[3:] {
if a != nil { if a != nil {
variadicArgs[i] = a.(interface{}) variadicArgs[i] = a.(any)
} }
} }
run(args[0].(context.Context), args[1].(string), args[2].(dbus.Flags), variadicArgs...) arg3 = variadicArgs
run(
arg0,
arg1,
arg2,
arg3...,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_CallWithContext_Call) Return(_a0 *dbus.Call) *MockBusObject_CallWithContext_Call { func (_c *MockBusObject_CallWithContext_Call) Return(call *dbus.Call) *MockBusObject_CallWithContext_Call {
_c.Call.Return(_a0) _c.Call.Return(call)
return _c return _c
} }
func (_c *MockBusObject_CallWithContext_Call) RunAndReturn(run func(context.Context, string, dbus.Flags, ...interface{}) *dbus.Call) *MockBusObject_CallWithContext_Call { func (_c *MockBusObject_CallWithContext_Call) RunAndReturn(run func(ctx context.Context, method string, flags dbus.Flags, args ...any) *dbus.Call) *MockBusObject_CallWithContext_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Destination provides a mock function with no fields // Destination provides a mock function for the type MockBusObject
func (_m *MockBusObject) Destination() string { func (_mock *MockBusObject) Destination() string {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Destination") panic("no return value specified for Destination")
} }
var r0 string var r0 string
if rf, ok := ret.Get(0).(func() string); ok { if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(string) r0 = ret.Get(0).(string)
} }
return r0 return r0
} }
@@ -242,8 +302,8 @@ func (_c *MockBusObject_Destination_Call) Run(run func()) *MockBusObject_Destina
return _c return _c
} }
func (_c *MockBusObject_Destination_Call) Return(_a0 string) *MockBusObject_Destination_Call { func (_c *MockBusObject_Destination_Call) Return(s string) *MockBusObject_Destination_Call {
_c.Call.Return(_a0) _c.Call.Return(s)
return _c return _c
} }
@@ -252,9 +312,9 @@ func (_c *MockBusObject_Destination_Call) RunAndReturn(run func() string) *MockB
return _c return _c
} }
// GetProperty provides a mock function with given fields: p // GetProperty provides a mock function for the type MockBusObject
func (_m *MockBusObject) GetProperty(p string) (dbus.Variant, error) { func (_mock *MockBusObject) GetProperty(p string) (dbus.Variant, error) {
ret := _m.Called(p) ret := _mock.Called(p)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetProperty") panic("no return value specified for GetProperty")
@@ -262,21 +322,19 @@ func (_m *MockBusObject) GetProperty(p string) (dbus.Variant, error) {
var r0 dbus.Variant var r0 dbus.Variant
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(string) (dbus.Variant, error)); ok { if returnFunc, ok := ret.Get(0).(func(string) (dbus.Variant, error)); ok {
return rf(p) return returnFunc(p)
} }
if rf, ok := ret.Get(0).(func(string) dbus.Variant); ok { if returnFunc, ok := ret.Get(0).(func(string) dbus.Variant); ok {
r0 = rf(p) r0 = returnFunc(p)
} else { } else {
r0 = ret.Get(0).(dbus.Variant) r0 = ret.Get(0).(dbus.Variant)
} }
if returnFunc, ok := ret.Get(1).(func(string) error); ok {
if rf, ok := ret.Get(1).(func(string) error); ok { r1 = returnFunc(p)
r1 = rf(p)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -287,47 +345,52 @@ type MockBusObject_GetProperty_Call struct {
// GetProperty is a helper method to define mock.On call // GetProperty is a helper method to define mock.On call
// - p string // - p string
func (_e *MockBusObject_Expecter) GetProperty(p interface{}) *MockBusObject_GetProperty_Call { func (_e *MockBusObject_Expecter) GetProperty(p any) *MockBusObject_GetProperty_Call {
return &MockBusObject_GetProperty_Call{Call: _e.mock.On("GetProperty", p)} return &MockBusObject_GetProperty_Call{Call: _e.mock.On("GetProperty", p)}
} }
func (_c *MockBusObject_GetProperty_Call) Run(run func(p string)) *MockBusObject_GetProperty_Call { func (_c *MockBusObject_GetProperty_Call) Run(run func(p string)) *MockBusObject_GetProperty_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_GetProperty_Call) Return(_a0 dbus.Variant, _a1 error) *MockBusObject_GetProperty_Call { func (_c *MockBusObject_GetProperty_Call) Return(variant dbus.Variant, err error) *MockBusObject_GetProperty_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(variant, err)
return _c return _c
} }
func (_c *MockBusObject_GetProperty_Call) RunAndReturn(run func(string) (dbus.Variant, error)) *MockBusObject_GetProperty_Call { func (_c *MockBusObject_GetProperty_Call) RunAndReturn(run func(p string) (dbus.Variant, error)) *MockBusObject_GetProperty_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Go provides a mock function with given fields: method, flags, ch, args // Go provides a mock function for the type MockBusObject
func (_m *MockBusObject) Go(method string, flags dbus.Flags, ch chan *dbus.Call, args ...interface{}) *dbus.Call { func (_mock *MockBusObject) Go(method string, flags dbus.Flags, ch chan *dbus.Call, args ...any) *dbus.Call {
var _ca []interface{} var _ca []any
_ca = append(_ca, method, flags, ch) _ca = append(_ca, method, flags, ch)
_ca = append(_ca, args...) _ca = append(_ca, args...)
ret := _m.Called(_ca...) ret := _mock.Called(_ca...)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Go") panic("no return value specified for Go")
} }
var r0 *dbus.Call var r0 *dbus.Call
if rf, ok := ret.Get(0).(func(string, dbus.Flags, chan *dbus.Call, ...interface{}) *dbus.Call); ok { if returnFunc, ok := ret.Get(0).(func(string, dbus.Flags, chan *dbus.Call, ...any) *dbus.Call); ok {
r0 = rf(method, flags, ch, args...) r0 = returnFunc(method, flags, ch, args...)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*dbus.Call) r0 = ret.Get(0).(*dbus.Call)
} }
} }
return r0 return r0
} }
@@ -340,55 +403,73 @@ type MockBusObject_Go_Call struct {
// - method string // - method string
// - flags dbus.Flags // - flags dbus.Flags
// - ch chan *dbus.Call // - ch chan *dbus.Call
// - args ...interface{} // - args ...any
func (_e *MockBusObject_Expecter) Go(method interface{}, flags interface{}, ch interface{}, args ...interface{}) *MockBusObject_Go_Call { func (_e *MockBusObject_Expecter) Go(method any, flags any, ch any, args ...any) *MockBusObject_Go_Call {
return &MockBusObject_Go_Call{Call: _e.mock.On("Go", return &MockBusObject_Go_Call{Call: _e.mock.On("Go",
append([]interface{}{method, flags, ch}, args...)...)} append([]any{method, flags, ch}, args...)...)}
} }
func (_c *MockBusObject_Go_Call) Run(run func(method string, flags dbus.Flags, ch chan *dbus.Call, args ...interface{})) *MockBusObject_Go_Call { func (_c *MockBusObject_Go_Call) Run(run func(method string, flags dbus.Flags, ch chan *dbus.Call, args ...any)) *MockBusObject_Go_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-3) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 dbus.Flags
if args[1] != nil {
arg1 = args[1].(dbus.Flags)
}
var arg2 chan *dbus.Call
if args[2] != nil {
arg2 = args[2].(chan *dbus.Call)
}
var arg3 []any
variadicArgs := make([]any, len(args)-3)
for i, a := range args[3:] { for i, a := range args[3:] {
if a != nil { if a != nil {
variadicArgs[i] = a.(interface{}) variadicArgs[i] = a.(any)
} }
} }
run(args[0].(string), args[1].(dbus.Flags), args[2].(chan *dbus.Call), variadicArgs...) arg3 = variadicArgs
run(
arg0,
arg1,
arg2,
arg3...,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_Go_Call) Return(_a0 *dbus.Call) *MockBusObject_Go_Call { func (_c *MockBusObject_Go_Call) Return(call *dbus.Call) *MockBusObject_Go_Call {
_c.Call.Return(_a0) _c.Call.Return(call)
return _c return _c
} }
func (_c *MockBusObject_Go_Call) RunAndReturn(run func(string, dbus.Flags, chan *dbus.Call, ...interface{}) *dbus.Call) *MockBusObject_Go_Call { func (_c *MockBusObject_Go_Call) RunAndReturn(run func(method string, flags dbus.Flags, ch chan *dbus.Call, args ...any) *dbus.Call) *MockBusObject_Go_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// GoWithContext provides a mock function with given fields: ctx, method, flags, ch, args // GoWithContext provides a mock function for the type MockBusObject
func (_m *MockBusObject) GoWithContext(ctx context.Context, method string, flags dbus.Flags, ch chan *dbus.Call, args ...interface{}) *dbus.Call { func (_mock *MockBusObject) GoWithContext(ctx context.Context, method string, flags dbus.Flags, ch chan *dbus.Call, args ...any) *dbus.Call {
var _ca []interface{} var _ca []any
_ca = append(_ca, ctx, method, flags, ch) _ca = append(_ca, ctx, method, flags, ch)
_ca = append(_ca, args...) _ca = append(_ca, args...)
ret := _m.Called(_ca...) ret := _mock.Called(_ca...)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GoWithContext") panic("no return value specified for GoWithContext")
} }
var r0 *dbus.Call var r0 *dbus.Call
if rf, ok := ret.Get(0).(func(context.Context, string, dbus.Flags, chan *dbus.Call, ...interface{}) *dbus.Call); ok { if returnFunc, ok := ret.Get(0).(func(context.Context, string, dbus.Flags, chan *dbus.Call, ...any) *dbus.Call); ok {
r0 = rf(ctx, method, flags, ch, args...) r0 = returnFunc(ctx, method, flags, ch, args...)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*dbus.Call) r0 = ret.Get(0).(*dbus.Call)
} }
} }
return r0 return r0
} }
@@ -402,50 +483,73 @@ type MockBusObject_GoWithContext_Call struct {
// - method string // - method string
// - flags dbus.Flags // - flags dbus.Flags
// - ch chan *dbus.Call // - ch chan *dbus.Call
// - args ...interface{} // - args ...any
func (_e *MockBusObject_Expecter) GoWithContext(ctx interface{}, method interface{}, flags interface{}, ch interface{}, args ...interface{}) *MockBusObject_GoWithContext_Call { func (_e *MockBusObject_Expecter) GoWithContext(ctx any, method any, flags any, ch any, args ...any) *MockBusObject_GoWithContext_Call {
return &MockBusObject_GoWithContext_Call{Call: _e.mock.On("GoWithContext", return &MockBusObject_GoWithContext_Call{Call: _e.mock.On("GoWithContext",
append([]interface{}{ctx, method, flags, ch}, args...)...)} append([]any{ctx, method, flags, ch}, args...)...)}
} }
func (_c *MockBusObject_GoWithContext_Call) Run(run func(ctx context.Context, method string, flags dbus.Flags, ch chan *dbus.Call, args ...interface{})) *MockBusObject_GoWithContext_Call { func (_c *MockBusObject_GoWithContext_Call) Run(run func(ctx context.Context, method string, flags dbus.Flags, ch chan *dbus.Call, args ...any)) *MockBusObject_GoWithContext_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-4) var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 dbus.Flags
if args[2] != nil {
arg2 = args[2].(dbus.Flags)
}
var arg3 chan *dbus.Call
if args[3] != nil {
arg3 = args[3].(chan *dbus.Call)
}
var arg4 []any
variadicArgs := make([]any, len(args)-4)
for i, a := range args[4:] { for i, a := range args[4:] {
if a != nil { if a != nil {
variadicArgs[i] = a.(interface{}) variadicArgs[i] = a.(any)
} }
} }
run(args[0].(context.Context), args[1].(string), args[2].(dbus.Flags), args[3].(chan *dbus.Call), variadicArgs...) arg4 = variadicArgs
run(
arg0,
arg1,
arg2,
arg3,
arg4...,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_GoWithContext_Call) Return(_a0 *dbus.Call) *MockBusObject_GoWithContext_Call { func (_c *MockBusObject_GoWithContext_Call) Return(call *dbus.Call) *MockBusObject_GoWithContext_Call {
_c.Call.Return(_a0) _c.Call.Return(call)
return _c return _c
} }
func (_c *MockBusObject_GoWithContext_Call) RunAndReturn(run func(context.Context, string, dbus.Flags, chan *dbus.Call, ...interface{}) *dbus.Call) *MockBusObject_GoWithContext_Call { func (_c *MockBusObject_GoWithContext_Call) RunAndReturn(run func(ctx context.Context, method string, flags dbus.Flags, ch chan *dbus.Call, args ...any) *dbus.Call) *MockBusObject_GoWithContext_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Path provides a mock function with no fields // Path provides a mock function for the type MockBusObject
func (_m *MockBusObject) Path() dbus.ObjectPath { func (_mock *MockBusObject) Path() dbus.ObjectPath {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Path") panic("no return value specified for Path")
} }
var r0 dbus.ObjectPath var r0 dbus.ObjectPath
if rf, ok := ret.Get(0).(func() dbus.ObjectPath); ok { if returnFunc, ok := ret.Get(0).(func() dbus.ObjectPath); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Get(0).(dbus.ObjectPath) r0 = ret.Get(0).(dbus.ObjectPath)
} }
return r0 return r0
} }
@@ -466,8 +570,8 @@ func (_c *MockBusObject_Path_Call) Run(run func()) *MockBusObject_Path_Call {
return _c return _c
} }
func (_c *MockBusObject_Path_Call) Return(_a0 dbus.ObjectPath) *MockBusObject_Path_Call { func (_c *MockBusObject_Path_Call) Return(objectPath dbus.ObjectPath) *MockBusObject_Path_Call {
_c.Call.Return(_a0) _c.Call.Return(objectPath)
return _c return _c
} }
@@ -476,30 +580,30 @@ func (_c *MockBusObject_Path_Call) RunAndReturn(run func() dbus.ObjectPath) *Moc
return _c return _c
} }
// RemoveMatchSignal provides a mock function with given fields: iface, member, options // RemoveMatchSignal provides a mock function for the type MockBusObject
func (_m *MockBusObject) RemoveMatchSignal(iface string, member string, options ...dbus.MatchOption) *dbus.Call { func (_mock *MockBusObject) RemoveMatchSignal(iface string, member string, options ...dbus.MatchOption) *dbus.Call {
_va := make([]interface{}, len(options)) // dbus.MatchOption
_va := make([]any, len(options))
for _i := range options { for _i := range options {
_va[_i] = options[_i] _va[_i] = options[_i]
} }
var _ca []interface{} var _ca []any
_ca = append(_ca, iface, member) _ca = append(_ca, iface, member)
_ca = append(_ca, _va...) _ca = append(_ca, _va...)
ret := _m.Called(_ca...) ret := _mock.Called(_ca...)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for RemoveMatchSignal") panic("no return value specified for RemoveMatchSignal")
} }
var r0 *dbus.Call var r0 *dbus.Call
if rf, ok := ret.Get(0).(func(string, string, ...dbus.MatchOption) *dbus.Call); ok { if returnFunc, ok := ret.Get(0).(func(string, string, ...dbus.MatchOption) *dbus.Call); ok {
r0 = rf(iface, member, options...) r0 = returnFunc(iface, member, options...)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*dbus.Call) r0 = ret.Get(0).(*dbus.Call)
} }
} }
return r0 return r0
} }
@@ -512,49 +616,62 @@ type MockBusObject_RemoveMatchSignal_Call struct {
// - iface string // - iface string
// - member string // - member string
// - options ...dbus.MatchOption // - options ...dbus.MatchOption
func (_e *MockBusObject_Expecter) RemoveMatchSignal(iface interface{}, member interface{}, options ...interface{}) *MockBusObject_RemoveMatchSignal_Call { func (_e *MockBusObject_Expecter) RemoveMatchSignal(iface any, member any, options ...any) *MockBusObject_RemoveMatchSignal_Call {
return &MockBusObject_RemoveMatchSignal_Call{Call: _e.mock.On("RemoveMatchSignal", return &MockBusObject_RemoveMatchSignal_Call{Call: _e.mock.On("RemoveMatchSignal",
append([]interface{}{iface, member}, options...)...)} append([]any{iface, member}, options...)...)}
} }
func (_c *MockBusObject_RemoveMatchSignal_Call) Run(run func(iface string, member string, options ...dbus.MatchOption)) *MockBusObject_RemoveMatchSignal_Call { func (_c *MockBusObject_RemoveMatchSignal_Call) Run(run func(iface string, member string, options ...dbus.MatchOption)) *MockBusObject_RemoveMatchSignal_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 []dbus.MatchOption
variadicArgs := make([]dbus.MatchOption, len(args)-2) variadicArgs := make([]dbus.MatchOption, len(args)-2)
for i, a := range args[2:] { for i, a := range args[2:] {
if a != nil { if a != nil {
variadicArgs[i] = a.(dbus.MatchOption) variadicArgs[i] = a.(dbus.MatchOption)
} }
} }
run(args[0].(string), args[1].(string), variadicArgs...) arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_RemoveMatchSignal_Call) Return(_a0 *dbus.Call) *MockBusObject_RemoveMatchSignal_Call { func (_c *MockBusObject_RemoveMatchSignal_Call) Return(call *dbus.Call) *MockBusObject_RemoveMatchSignal_Call {
_c.Call.Return(_a0) _c.Call.Return(call)
return _c return _c
} }
func (_c *MockBusObject_RemoveMatchSignal_Call) RunAndReturn(run func(string, string, ...dbus.MatchOption) *dbus.Call) *MockBusObject_RemoveMatchSignal_Call { func (_c *MockBusObject_RemoveMatchSignal_Call) RunAndReturn(run func(iface string, member string, options ...dbus.MatchOption) *dbus.Call) *MockBusObject_RemoveMatchSignal_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// SetProperty provides a mock function with given fields: p, v // SetProperty provides a mock function for the type MockBusObject
func (_m *MockBusObject) SetProperty(p string, v interface{}) error { func (_mock *MockBusObject) SetProperty(p string, v any) error {
ret := _m.Called(p, v) ret := _mock.Called(p, v)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for SetProperty") panic("no return value specified for SetProperty")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(string, interface{}) error); ok { if returnFunc, ok := ret.Get(0).(func(string, any) error); ok {
r0 = rf(p, v) r0 = returnFunc(p, v)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -565,43 +682,53 @@ type MockBusObject_SetProperty_Call struct {
// SetProperty is a helper method to define mock.On call // SetProperty is a helper method to define mock.On call
// - p string // - p string
// - v interface{} // - v any
func (_e *MockBusObject_Expecter) SetProperty(p interface{}, v interface{}) *MockBusObject_SetProperty_Call { func (_e *MockBusObject_Expecter) SetProperty(p any, v any) *MockBusObject_SetProperty_Call {
return &MockBusObject_SetProperty_Call{Call: _e.mock.On("SetProperty", p, v)} return &MockBusObject_SetProperty_Call{Call: _e.mock.On("SetProperty", p, v)}
} }
func (_c *MockBusObject_SetProperty_Call) Run(run func(p string, v interface{})) *MockBusObject_SetProperty_Call { func (_c *MockBusObject_SetProperty_Call) Run(run func(p string, v any)) *MockBusObject_SetProperty_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string), args[1].(interface{})) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 any
if args[1] != nil {
arg1 = args[1].(any)
}
run(
arg0,
arg1,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_SetProperty_Call) Return(_a0 error) *MockBusObject_SetProperty_Call { func (_c *MockBusObject_SetProperty_Call) Return(err error) *MockBusObject_SetProperty_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockBusObject_SetProperty_Call) RunAndReturn(run func(string, interface{}) error) *MockBusObject_SetProperty_Call { func (_c *MockBusObject_SetProperty_Call) RunAndReturn(run func(p string, v any) error) *MockBusObject_SetProperty_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// StoreProperty provides a mock function with given fields: p, value // StoreProperty provides a mock function for the type MockBusObject
func (_m *MockBusObject) StoreProperty(p string, value interface{}) error { func (_mock *MockBusObject) StoreProperty(p string, value any) error {
ret := _m.Called(p, value) ret := _mock.Called(p, value)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for StoreProperty") panic("no return value specified for StoreProperty")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(string, interface{}) error); ok { if returnFunc, ok := ret.Get(0).(func(string, any) error); ok {
r0 = rf(p, value) r0 = returnFunc(p, value)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -612,38 +739,35 @@ type MockBusObject_StoreProperty_Call struct {
// StoreProperty is a helper method to define mock.On call // StoreProperty is a helper method to define mock.On call
// - p string // - p string
// - value interface{} // - value any
func (_e *MockBusObject_Expecter) StoreProperty(p interface{}, value interface{}) *MockBusObject_StoreProperty_Call { func (_e *MockBusObject_Expecter) StoreProperty(p any, value any) *MockBusObject_StoreProperty_Call {
return &MockBusObject_StoreProperty_Call{Call: _e.mock.On("StoreProperty", p, value)} return &MockBusObject_StoreProperty_Call{Call: _e.mock.On("StoreProperty", p, value)}
} }
func (_c *MockBusObject_StoreProperty_Call) Run(run func(p string, value interface{})) *MockBusObject_StoreProperty_Call { func (_c *MockBusObject_StoreProperty_Call) Run(run func(p string, value any)) *MockBusObject_StoreProperty_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string), args[1].(interface{})) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 any
if args[1] != nil {
arg1 = args[1].(any)
}
run(
arg0,
arg1,
)
}) })
return _c return _c
} }
func (_c *MockBusObject_StoreProperty_Call) Return(_a0 error) *MockBusObject_StoreProperty_Call { func (_c *MockBusObject_StoreProperty_Call) Return(err error) *MockBusObject_StoreProperty_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockBusObject_StoreProperty_Call) RunAndReturn(run func(string, interface{}) error) *MockBusObject_StoreProperty_Call { func (_c *MockBusObject_StoreProperty_Call) RunAndReturn(run func(p string, value any) error) *MockBusObject_StoreProperty_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockBusObject creates a new instance of MockBusObject. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockBusObject(t interface {
mock.TestingT
Cleanup(func())
}) *MockBusObject {
mock := &MockBusObject{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -1,8 +1,26 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package plugins package plugins
import mock "github.com/stretchr/testify/mock" import (
mock "github.com/stretchr/testify/mock"
)
// NewMockGitClient creates a new instance of MockGitClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockGitClient(t interface {
mock.TestingT
Cleanup(func())
}) *MockGitClient {
mock := &MockGitClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockGitClient is an autogenerated mock type for the GitClient type // MockGitClient is an autogenerated mock type for the GitClient type
type MockGitClient struct { type MockGitClient struct {
@@ -17,9 +35,9 @@ func (_m *MockGitClient) EXPECT() *MockGitClient_Expecter {
return &MockGitClient_Expecter{mock: &_m.Mock} return &MockGitClient_Expecter{mock: &_m.Mock}
} }
// HasUpdates provides a mock function with given fields: path // HasUpdates provides a mock function for the type MockGitClient
func (_m *MockGitClient) HasUpdates(path string) (bool, error) { func (_mock *MockGitClient) HasUpdates(path string) (bool, error) {
ret := _m.Called(path) ret := _mock.Called(path)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for HasUpdates") panic("no return value specified for HasUpdates")
@@ -27,21 +45,19 @@ func (_m *MockGitClient) HasUpdates(path string) (bool, error) {
var r0 bool var r0 bool
var r1 error var r1 error
if rf, ok := ret.Get(0).(func(string) (bool, error)); ok { if returnFunc, ok := ret.Get(0).(func(string) (bool, error)); ok {
return rf(path) return returnFunc(path)
} }
if rf, ok := ret.Get(0).(func(string) bool); ok { if returnFunc, ok := ret.Get(0).(func(string) bool); ok {
r0 = rf(path) r0 = returnFunc(path)
} else { } else {
r0 = ret.Get(0).(bool) r0 = ret.Get(0).(bool)
} }
if returnFunc, ok := ret.Get(1).(func(string) error); ok {
if rf, ok := ret.Get(1).(func(string) error); ok { r1 = returnFunc(path)
r1 = rf(path)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -58,36 +74,41 @@ func (_e *MockGitClient_Expecter) HasUpdates(path any) *MockGitClient_HasUpdates
func (_c *MockGitClient_HasUpdates_Call) Run(run func(path string)) *MockGitClient_HasUpdates_Call { func (_c *MockGitClient_HasUpdates_Call) Run(run func(path string)) *MockGitClient_HasUpdates_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockGitClient_HasUpdates_Call) Return(_a0 bool, _a1 error) *MockGitClient_HasUpdates_Call { func (_c *MockGitClient_HasUpdates_Call) Return(b bool, err error) *MockGitClient_HasUpdates_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(b, err)
return _c return _c
} }
func (_c *MockGitClient_HasUpdates_Call) RunAndReturn(run func(string) (bool, error)) *MockGitClient_HasUpdates_Call { func (_c *MockGitClient_HasUpdates_Call) RunAndReturn(run func(path string) (bool, error)) *MockGitClient_HasUpdates_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// PlainClone provides a mock function with given fields: path, url // PlainClone provides a mock function for the type MockGitClient
func (_m *MockGitClient) PlainClone(path string, url string) error { func (_mock *MockGitClient) PlainClone(path string, url string) error {
ret := _m.Called(path, url) ret := _mock.Called(path, url)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for PlainClone") panic("no return value specified for PlainClone")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(string, string) error); ok { if returnFunc, ok := ret.Get(0).(func(string, string) error); ok {
r0 = rf(path, url) r0 = returnFunc(path, url)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -105,36 +126,46 @@ func (_e *MockGitClient_Expecter) PlainClone(path any, url any) *MockGitClient_P
func (_c *MockGitClient_PlainClone_Call) Run(run func(path string, url string)) *MockGitClient_PlainClone_Call { func (_c *MockGitClient_PlainClone_Call) Run(run func(path string, url string)) *MockGitClient_PlainClone_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string), args[1].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
run(
arg0,
arg1,
)
}) })
return _c return _c
} }
func (_c *MockGitClient_PlainClone_Call) Return(_a0 error) *MockGitClient_PlainClone_Call { func (_c *MockGitClient_PlainClone_Call) Return(err error) *MockGitClient_PlainClone_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockGitClient_PlainClone_Call) RunAndReturn(run func(string, string) error) *MockGitClient_PlainClone_Call { func (_c *MockGitClient_PlainClone_Call) RunAndReturn(run func(path string, url string) error) *MockGitClient_PlainClone_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Pull provides a mock function with given fields: path // Pull provides a mock function for the type MockGitClient
func (_m *MockGitClient) Pull(path string) error { func (_mock *MockGitClient) Pull(path string) error {
ret := _m.Called(path) ret := _mock.Called(path)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Pull") panic("no return value specified for Pull")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok { if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(path) r0 = returnFunc(path)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -151,31 +182,23 @@ func (_e *MockGitClient_Expecter) Pull(path any) *MockGitClient_Pull_Call {
func (_c *MockGitClient_Pull_Call) Run(run func(path string)) *MockGitClient_Pull_Call { func (_c *MockGitClient_Pull_Call) Run(run func(path string)) *MockGitClient_Pull_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(string)) var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockGitClient_Pull_Call) Return(_a0 error) *MockGitClient_Pull_Call { func (_c *MockGitClient_Pull_Call) Return(err error) *MockGitClient_Pull_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockGitClient_Pull_Call) RunAndReturn(run func(string) error) *MockGitClient_Pull_Call { func (_c *MockGitClient_Pull_Call) RunAndReturn(run func(path string) error) *MockGitClient_Pull_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockGitClient creates a new instance of MockGitClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockGitClient(t interface {
mock.TestingT
Cleanup(func())
}) *MockGitClient {
mock := &MockGitClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
+124 -103
View File
@@ -1,15 +1,30 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package net package net
import ( import (
net "net" "net"
"time"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
time "time"
) )
// NewMockConn creates a new instance of MockConn. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockConn(t interface {
mock.TestingT
Cleanup(func())
}) *MockConn {
mock := &MockConn{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockConn is an autogenerated mock type for the Conn type // MockConn is an autogenerated mock type for the Conn type
type MockConn struct { type MockConn struct {
mock.Mock mock.Mock
@@ -23,21 +38,20 @@ func (_m *MockConn) EXPECT() *MockConn_Expecter {
return &MockConn_Expecter{mock: &_m.Mock} return &MockConn_Expecter{mock: &_m.Mock}
} }
// Close provides a mock function with no fields // Close provides a mock function for the type MockConn
func (_m *MockConn) Close() error { func (_mock *MockConn) Close() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Close") panic("no return value specified for Close")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -58,8 +72,8 @@ func (_c *MockConn_Close_Call) Run(run func()) *MockConn_Close_Call {
return _c return _c
} }
func (_c *MockConn_Close_Call) Return(_a0 error) *MockConn_Close_Call { func (_c *MockConn_Close_Call) Return(err error) *MockConn_Close_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -68,23 +82,22 @@ func (_c *MockConn_Close_Call) RunAndReturn(run func() error) *MockConn_Close_Ca
return _c return _c
} }
// LocalAddr provides a mock function with no fields // LocalAddr provides a mock function for the type MockConn
func (_m *MockConn) LocalAddr() net.Addr { func (_mock *MockConn) LocalAddr() net.Addr {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for LocalAddr") panic("no return value specified for LocalAddr")
} }
var r0 net.Addr var r0 net.Addr
if rf, ok := ret.Get(0).(func() net.Addr); ok { if returnFunc, ok := ret.Get(0).(func() net.Addr); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(net.Addr) r0 = ret.Get(0).(net.Addr)
} }
} }
return r0 return r0
} }
@@ -105,8 +118,8 @@ func (_c *MockConn_LocalAddr_Call) Run(run func()) *MockConn_LocalAddr_Call {
return _c return _c
} }
func (_c *MockConn_LocalAddr_Call) Return(_a0 net.Addr) *MockConn_LocalAddr_Call { func (_c *MockConn_LocalAddr_Call) Return(addr net.Addr) *MockConn_LocalAddr_Call {
_c.Call.Return(_a0) _c.Call.Return(addr)
return _c return _c
} }
@@ -115,9 +128,9 @@ func (_c *MockConn_LocalAddr_Call) RunAndReturn(run func() net.Addr) *MockConn_L
return _c return _c
} }
// Read provides a mock function with given fields: b // Read provides a mock function for the type MockConn
func (_m *MockConn) Read(b []byte) (int, error) { func (_mock *MockConn) Read(b []byte) (int, error) {
ret := _m.Called(b) ret := _mock.Called(b)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Read") panic("no return value specified for Read")
@@ -125,21 +138,19 @@ func (_m *MockConn) Read(b []byte) (int, error) {
var r0 int var r0 int
var r1 error var r1 error
if rf, ok := ret.Get(0).(func([]byte) (int, error)); ok { if returnFunc, ok := ret.Get(0).(func([]byte) (int, error)); ok {
return rf(b) return returnFunc(b)
} }
if rf, ok := ret.Get(0).(func([]byte) int); ok { if returnFunc, ok := ret.Get(0).(func([]byte) int); ok {
r0 = rf(b) r0 = returnFunc(b)
} else { } else {
r0 = ret.Get(0).(int) r0 = ret.Get(0).(int)
} }
if returnFunc, ok := ret.Get(1).(func([]byte) error); ok {
if rf, ok := ret.Get(1).(func([]byte) error); ok { r1 = returnFunc(b)
r1 = rf(b)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -150,13 +161,19 @@ type MockConn_Read_Call struct {
// Read is a helper method to define mock.On call // Read is a helper method to define mock.On call
// - b []byte // - b []byte
func (_e *MockConn_Expecter) Read(b interface{}) *MockConn_Read_Call { func (_e *MockConn_Expecter) Read(b any) *MockConn_Read_Call {
return &MockConn_Read_Call{Call: _e.mock.On("Read", b)} return &MockConn_Read_Call{Call: _e.mock.On("Read", b)}
} }
func (_c *MockConn_Read_Call) Run(run func(b []byte)) *MockConn_Read_Call { func (_c *MockConn_Read_Call) Run(run func(b []byte)) *MockConn_Read_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].([]byte)) var arg0 []byte
if args[0] != nil {
arg0 = args[0].([]byte)
}
run(
arg0,
)
}) })
return _c return _c
} }
@@ -166,28 +183,27 @@ func (_c *MockConn_Read_Call) Return(n int, err error) *MockConn_Read_Call {
return _c return _c
} }
func (_c *MockConn_Read_Call) RunAndReturn(run func([]byte) (int, error)) *MockConn_Read_Call { func (_c *MockConn_Read_Call) RunAndReturn(run func(b []byte) (int, error)) *MockConn_Read_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// RemoteAddr provides a mock function with no fields // RemoteAddr provides a mock function for the type MockConn
func (_m *MockConn) RemoteAddr() net.Addr { func (_mock *MockConn) RemoteAddr() net.Addr {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for RemoteAddr") panic("no return value specified for RemoteAddr")
} }
var r0 net.Addr var r0 net.Addr
if rf, ok := ret.Get(0).(func() net.Addr); ok { if returnFunc, ok := ret.Get(0).(func() net.Addr); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(net.Addr) r0 = ret.Get(0).(net.Addr)
} }
} }
return r0 return r0
} }
@@ -208,8 +224,8 @@ func (_c *MockConn_RemoteAddr_Call) Run(run func()) *MockConn_RemoteAddr_Call {
return _c return _c
} }
func (_c *MockConn_RemoteAddr_Call) Return(_a0 net.Addr) *MockConn_RemoteAddr_Call { func (_c *MockConn_RemoteAddr_Call) Return(addr net.Addr) *MockConn_RemoteAddr_Call {
_c.Call.Return(_a0) _c.Call.Return(addr)
return _c return _c
} }
@@ -218,21 +234,20 @@ func (_c *MockConn_RemoteAddr_Call) RunAndReturn(run func() net.Addr) *MockConn_
return _c return _c
} }
// SetDeadline provides a mock function with given fields: t // SetDeadline provides a mock function for the type MockConn
func (_m *MockConn) SetDeadline(t time.Time) error { func (_mock *MockConn) SetDeadline(t time.Time) error {
ret := _m.Called(t) ret := _mock.Called(t)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for SetDeadline") panic("no return value specified for SetDeadline")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(time.Time) error); ok { if returnFunc, ok := ret.Get(0).(func(time.Time) error); ok {
r0 = rf(t) r0 = returnFunc(t)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -243,42 +258,47 @@ type MockConn_SetDeadline_Call struct {
// SetDeadline is a helper method to define mock.On call // SetDeadline is a helper method to define mock.On call
// - t time.Time // - t time.Time
func (_e *MockConn_Expecter) SetDeadline(t interface{}) *MockConn_SetDeadline_Call { func (_e *MockConn_Expecter) SetDeadline(t any) *MockConn_SetDeadline_Call {
return &MockConn_SetDeadline_Call{Call: _e.mock.On("SetDeadline", t)} return &MockConn_SetDeadline_Call{Call: _e.mock.On("SetDeadline", t)}
} }
func (_c *MockConn_SetDeadline_Call) Run(run func(t time.Time)) *MockConn_SetDeadline_Call { func (_c *MockConn_SetDeadline_Call) Run(run func(t time.Time)) *MockConn_SetDeadline_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(time.Time)) var arg0 time.Time
if args[0] != nil {
arg0 = args[0].(time.Time)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockConn_SetDeadline_Call) Return(_a0 error) *MockConn_SetDeadline_Call { func (_c *MockConn_SetDeadline_Call) Return(err error) *MockConn_SetDeadline_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockConn_SetDeadline_Call) RunAndReturn(run func(time.Time) error) *MockConn_SetDeadline_Call { func (_c *MockConn_SetDeadline_Call) RunAndReturn(run func(t time.Time) error) *MockConn_SetDeadline_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// SetReadDeadline provides a mock function with given fields: t // SetReadDeadline provides a mock function for the type MockConn
func (_m *MockConn) SetReadDeadline(t time.Time) error { func (_mock *MockConn) SetReadDeadline(t time.Time) error {
ret := _m.Called(t) ret := _mock.Called(t)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for SetReadDeadline") panic("no return value specified for SetReadDeadline")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(time.Time) error); ok { if returnFunc, ok := ret.Get(0).(func(time.Time) error); ok {
r0 = rf(t) r0 = returnFunc(t)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -289,42 +309,47 @@ type MockConn_SetReadDeadline_Call struct {
// SetReadDeadline is a helper method to define mock.On call // SetReadDeadline is a helper method to define mock.On call
// - t time.Time // - t time.Time
func (_e *MockConn_Expecter) SetReadDeadline(t interface{}) *MockConn_SetReadDeadline_Call { func (_e *MockConn_Expecter) SetReadDeadline(t any) *MockConn_SetReadDeadline_Call {
return &MockConn_SetReadDeadline_Call{Call: _e.mock.On("SetReadDeadline", t)} return &MockConn_SetReadDeadline_Call{Call: _e.mock.On("SetReadDeadline", t)}
} }
func (_c *MockConn_SetReadDeadline_Call) Run(run func(t time.Time)) *MockConn_SetReadDeadline_Call { func (_c *MockConn_SetReadDeadline_Call) Run(run func(t time.Time)) *MockConn_SetReadDeadline_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(time.Time)) var arg0 time.Time
if args[0] != nil {
arg0 = args[0].(time.Time)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockConn_SetReadDeadline_Call) Return(_a0 error) *MockConn_SetReadDeadline_Call { func (_c *MockConn_SetReadDeadline_Call) Return(err error) *MockConn_SetReadDeadline_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockConn_SetReadDeadline_Call) RunAndReturn(run func(time.Time) error) *MockConn_SetReadDeadline_Call { func (_c *MockConn_SetReadDeadline_Call) RunAndReturn(run func(t time.Time) error) *MockConn_SetReadDeadline_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// SetWriteDeadline provides a mock function with given fields: t // SetWriteDeadline provides a mock function for the type MockConn
func (_m *MockConn) SetWriteDeadline(t time.Time) error { func (_mock *MockConn) SetWriteDeadline(t time.Time) error {
ret := _m.Called(t) ret := _mock.Called(t)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for SetWriteDeadline") panic("no return value specified for SetWriteDeadline")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(time.Time) error); ok { if returnFunc, ok := ret.Get(0).(func(time.Time) error); ok {
r0 = rf(t) r0 = returnFunc(t)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -335,30 +360,36 @@ type MockConn_SetWriteDeadline_Call struct {
// SetWriteDeadline is a helper method to define mock.On call // SetWriteDeadline is a helper method to define mock.On call
// - t time.Time // - t time.Time
func (_e *MockConn_Expecter) SetWriteDeadline(t interface{}) *MockConn_SetWriteDeadline_Call { func (_e *MockConn_Expecter) SetWriteDeadline(t any) *MockConn_SetWriteDeadline_Call {
return &MockConn_SetWriteDeadline_Call{Call: _e.mock.On("SetWriteDeadline", t)} return &MockConn_SetWriteDeadline_Call{Call: _e.mock.On("SetWriteDeadline", t)}
} }
func (_c *MockConn_SetWriteDeadline_Call) Run(run func(t time.Time)) *MockConn_SetWriteDeadline_Call { func (_c *MockConn_SetWriteDeadline_Call) Run(run func(t time.Time)) *MockConn_SetWriteDeadline_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(time.Time)) var arg0 time.Time
if args[0] != nil {
arg0 = args[0].(time.Time)
}
run(
arg0,
)
}) })
return _c return _c
} }
func (_c *MockConn_SetWriteDeadline_Call) Return(_a0 error) *MockConn_SetWriteDeadline_Call { func (_c *MockConn_SetWriteDeadline_Call) Return(err error) *MockConn_SetWriteDeadline_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
func (_c *MockConn_SetWriteDeadline_Call) RunAndReturn(run func(time.Time) error) *MockConn_SetWriteDeadline_Call { func (_c *MockConn_SetWriteDeadline_Call) RunAndReturn(run func(t time.Time) error) *MockConn_SetWriteDeadline_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// Write provides a mock function with given fields: b // Write provides a mock function for the type MockConn
func (_m *MockConn) Write(b []byte) (int, error) { func (_mock *MockConn) Write(b []byte) (int, error) {
ret := _m.Called(b) ret := _mock.Called(b)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Write") panic("no return value specified for Write")
@@ -366,21 +397,19 @@ func (_m *MockConn) Write(b []byte) (int, error) {
var r0 int var r0 int
var r1 error var r1 error
if rf, ok := ret.Get(0).(func([]byte) (int, error)); ok { if returnFunc, ok := ret.Get(0).(func([]byte) (int, error)); ok {
return rf(b) return returnFunc(b)
} }
if rf, ok := ret.Get(0).(func([]byte) int); ok { if returnFunc, ok := ret.Get(0).(func([]byte) int); ok {
r0 = rf(b) r0 = returnFunc(b)
} else { } else {
r0 = ret.Get(0).(int) r0 = ret.Get(0).(int)
} }
if returnFunc, ok := ret.Get(1).(func([]byte) error); ok {
if rf, ok := ret.Get(1).(func([]byte) error); ok { r1 = returnFunc(b)
r1 = rf(b)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -391,13 +420,19 @@ type MockConn_Write_Call struct {
// Write is a helper method to define mock.On call // Write is a helper method to define mock.On call
// - b []byte // - b []byte
func (_e *MockConn_Expecter) Write(b interface{}) *MockConn_Write_Call { func (_e *MockConn_Expecter) Write(b any) *MockConn_Write_Call {
return &MockConn_Write_Call{Call: _e.mock.On("Write", b)} return &MockConn_Write_Call{Call: _e.mock.On("Write", b)}
} }
func (_c *MockConn_Write_Call) Run(run func(b []byte)) *MockConn_Write_Call { func (_c *MockConn_Write_Call) Run(run func(b []byte)) *MockConn_Write_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].([]byte)) var arg0 []byte
if args[0] != nil {
arg0 = args[0].([]byte)
}
run(
arg0,
)
}) })
return _c return _c
} }
@@ -407,21 +442,7 @@ func (_c *MockConn_Write_Call) Return(n int, err error) *MockConn_Write_Call {
return _c return _c
} }
func (_c *MockConn_Write_Call) RunAndReturn(run func([]byte) (int, error)) *MockConn_Write_Call { func (_c *MockConn_Write_Call) RunAndReturn(run func(b []byte) (int, error)) *MockConn_Write_Call {
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockConn creates a new instance of MockConn. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockConn(t interface {
mock.TestingT
Cleanup(func())
}) *MockConn {
mock := &MockConn{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
File diff suppressed because it is too large Load Diff
+247 -225
View File
@@ -1,231 +1,12 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_utils package mocks_utils
import mock "github.com/stretchr/testify/mock" import (
mock "github.com/stretchr/testify/mock"
// MockAppChecker is an autogenerated mock type for the AppChecker type )
type MockAppChecker struct {
mock.Mock
}
type MockAppChecker_Expecter struct {
mock *mock.Mock
}
func (_m *MockAppChecker) EXPECT() *MockAppChecker_Expecter {
return &MockAppChecker_Expecter{mock: &_m.Mock}
}
// AnyCommandExists provides a mock function with given fields: cmds
func (_m *MockAppChecker) AnyCommandExists(cmds ...string) bool {
_va := make([]interface{}, len(cmds))
for _i := range cmds {
_va[_i] = cmds[_i]
}
var _ca []interface{}
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for AnyCommandExists")
}
var r0 bool
if rf, ok := ret.Get(0).(func(...string) bool); ok {
r0 = rf(cmds...)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_AnyCommandExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AnyCommandExists'
type MockAppChecker_AnyCommandExists_Call struct {
*mock.Call
}
// AnyCommandExists is a helper method to define mock.On call
// - cmds ...string
func (_e *MockAppChecker_Expecter) AnyCommandExists(cmds ...interface{}) *MockAppChecker_AnyCommandExists_Call {
return &MockAppChecker_AnyCommandExists_Call{Call: _e.mock.On("AnyCommandExists",
append([]interface{}{}, cmds...)...)}
}
func (_c *MockAppChecker_AnyCommandExists_Call) Run(run func(cmds ...string)) *MockAppChecker_AnyCommandExists_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]string, len(args)-0)
for i, a := range args[0:] {
if a != nil {
variadicArgs[i] = a.(string)
}
}
run(variadicArgs...)
})
return _c
}
func (_c *MockAppChecker_AnyCommandExists_Call) Return(_a0 bool) *MockAppChecker_AnyCommandExists_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockAppChecker_AnyCommandExists_Call) RunAndReturn(run func(...string) bool) *MockAppChecker_AnyCommandExists_Call {
_c.Call.Return(run)
return _c
}
// AnyFlatpakExists provides a mock function with given fields: flatpaks
func (_m *MockAppChecker) AnyFlatpakExists(flatpaks ...string) bool {
_va := make([]interface{}, len(flatpaks))
for _i := range flatpaks {
_va[_i] = flatpaks[_i]
}
var _ca []interface{}
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for AnyFlatpakExists")
}
var r0 bool
if rf, ok := ret.Get(0).(func(...string) bool); ok {
r0 = rf(flatpaks...)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_AnyFlatpakExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AnyFlatpakExists'
type MockAppChecker_AnyFlatpakExists_Call struct {
*mock.Call
}
// AnyFlatpakExists is a helper method to define mock.On call
// - flatpaks ...string
func (_e *MockAppChecker_Expecter) AnyFlatpakExists(flatpaks ...interface{}) *MockAppChecker_AnyFlatpakExists_Call {
return &MockAppChecker_AnyFlatpakExists_Call{Call: _e.mock.On("AnyFlatpakExists",
append([]interface{}{}, flatpaks...)...)}
}
func (_c *MockAppChecker_AnyFlatpakExists_Call) Run(run func(flatpaks ...string)) *MockAppChecker_AnyFlatpakExists_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]string, len(args)-0)
for i, a := range args[0:] {
if a != nil {
variadicArgs[i] = a.(string)
}
}
run(variadicArgs...)
})
return _c
}
func (_c *MockAppChecker_AnyFlatpakExists_Call) Return(_a0 bool) *MockAppChecker_AnyFlatpakExists_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockAppChecker_AnyFlatpakExists_Call) RunAndReturn(run func(...string) bool) *MockAppChecker_AnyFlatpakExists_Call {
_c.Call.Return(run)
return _c
}
// CommandExists provides a mock function with given fields: cmd
func (_m *MockAppChecker) CommandExists(cmd string) bool {
ret := _m.Called(cmd)
if len(ret) == 0 {
panic("no return value specified for CommandExists")
}
var r0 bool
if rf, ok := ret.Get(0).(func(string) bool); ok {
r0 = rf(cmd)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_CommandExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CommandExists'
type MockAppChecker_CommandExists_Call struct {
*mock.Call
}
// CommandExists is a helper method to define mock.On call
// - cmd string
func (_e *MockAppChecker_Expecter) CommandExists(cmd interface{}) *MockAppChecker_CommandExists_Call {
return &MockAppChecker_CommandExists_Call{Call: _e.mock.On("CommandExists", cmd)}
}
func (_c *MockAppChecker_CommandExists_Call) Run(run func(cmd string)) *MockAppChecker_CommandExists_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockAppChecker_CommandExists_Call) Return(_a0 bool) *MockAppChecker_CommandExists_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockAppChecker_CommandExists_Call) RunAndReturn(run func(string) bool) *MockAppChecker_CommandExists_Call {
_c.Call.Return(run)
return _c
}
// FlatpakExists provides a mock function with given fields: name
func (_m *MockAppChecker) FlatpakExists(name string) bool {
ret := _m.Called(name)
if len(ret) == 0 {
panic("no return value specified for FlatpakExists")
}
var r0 bool
if rf, ok := ret.Get(0).(func(string) bool); ok {
r0 = rf(name)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_FlatpakExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FlatpakExists'
type MockAppChecker_FlatpakExists_Call struct {
*mock.Call
}
// FlatpakExists is a helper method to define mock.On call
// - name string
func (_e *MockAppChecker_Expecter) FlatpakExists(name interface{}) *MockAppChecker_FlatpakExists_Call {
return &MockAppChecker_FlatpakExists_Call{Call: _e.mock.On("FlatpakExists", name)}
}
func (_c *MockAppChecker_FlatpakExists_Call) Run(run func(name string)) *MockAppChecker_FlatpakExists_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockAppChecker_FlatpakExists_Call) Return(_a0 bool) *MockAppChecker_FlatpakExists_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockAppChecker_FlatpakExists_Call) RunAndReturn(run func(string) bool) *MockAppChecker_FlatpakExists_Call {
_c.Call.Return(run)
return _c
}
// NewMockAppChecker creates a new instance of MockAppChecker. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // NewMockAppChecker creates a new instance of MockAppChecker. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value. // The first argument is typically a *testing.T value.
@@ -240,3 +21,244 @@ func NewMockAppChecker(t interface {
return mock return mock
} }
// MockAppChecker is an autogenerated mock type for the AppChecker type
type MockAppChecker struct {
mock.Mock
}
type MockAppChecker_Expecter struct {
mock *mock.Mock
}
func (_m *MockAppChecker) EXPECT() *MockAppChecker_Expecter {
return &MockAppChecker_Expecter{mock: &_m.Mock}
}
// AnyCommandExists provides a mock function for the type MockAppChecker
func (_mock *MockAppChecker) AnyCommandExists(cmds ...string) bool {
// string
_va := make([]any, len(cmds))
for _i := range cmds {
_va[_i] = cmds[_i]
}
var _ca []any
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for AnyCommandExists")
}
var r0 bool
if returnFunc, ok := ret.Get(0).(func(...string) bool); ok {
r0 = returnFunc(cmds...)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_AnyCommandExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AnyCommandExists'
type MockAppChecker_AnyCommandExists_Call struct {
*mock.Call
}
// AnyCommandExists is a helper method to define mock.On call
// - cmds ...string
func (_e *MockAppChecker_Expecter) AnyCommandExists(cmds ...any) *MockAppChecker_AnyCommandExists_Call {
return &MockAppChecker_AnyCommandExists_Call{Call: _e.mock.On("AnyCommandExists",
append([]any{}, cmds...)...)}
}
func (_c *MockAppChecker_AnyCommandExists_Call) Run(run func(cmds ...string)) *MockAppChecker_AnyCommandExists_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 []string
variadicArgs := make([]string, len(args)-0)
for i, a := range args[0:] {
if a != nil {
variadicArgs[i] = a.(string)
}
}
arg0 = variadicArgs
run(
arg0...,
)
})
return _c
}
func (_c *MockAppChecker_AnyCommandExists_Call) Return(b bool) *MockAppChecker_AnyCommandExists_Call {
_c.Call.Return(b)
return _c
}
func (_c *MockAppChecker_AnyCommandExists_Call) RunAndReturn(run func(cmds ...string) bool) *MockAppChecker_AnyCommandExists_Call {
_c.Call.Return(run)
return _c
}
// AnyFlatpakExists provides a mock function for the type MockAppChecker
func (_mock *MockAppChecker) AnyFlatpakExists(flatpaks ...string) bool {
// string
_va := make([]any, len(flatpaks))
for _i := range flatpaks {
_va[_i] = flatpaks[_i]
}
var _ca []any
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for AnyFlatpakExists")
}
var r0 bool
if returnFunc, ok := ret.Get(0).(func(...string) bool); ok {
r0 = returnFunc(flatpaks...)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_AnyFlatpakExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AnyFlatpakExists'
type MockAppChecker_AnyFlatpakExists_Call struct {
*mock.Call
}
// AnyFlatpakExists is a helper method to define mock.On call
// - flatpaks ...string
func (_e *MockAppChecker_Expecter) AnyFlatpakExists(flatpaks ...any) *MockAppChecker_AnyFlatpakExists_Call {
return &MockAppChecker_AnyFlatpakExists_Call{Call: _e.mock.On("AnyFlatpakExists",
append([]any{}, flatpaks...)...)}
}
func (_c *MockAppChecker_AnyFlatpakExists_Call) Run(run func(flatpaks ...string)) *MockAppChecker_AnyFlatpakExists_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 []string
variadicArgs := make([]string, len(args)-0)
for i, a := range args[0:] {
if a != nil {
variadicArgs[i] = a.(string)
}
}
arg0 = variadicArgs
run(
arg0...,
)
})
return _c
}
func (_c *MockAppChecker_AnyFlatpakExists_Call) Return(b bool) *MockAppChecker_AnyFlatpakExists_Call {
_c.Call.Return(b)
return _c
}
func (_c *MockAppChecker_AnyFlatpakExists_Call) RunAndReturn(run func(flatpaks ...string) bool) *MockAppChecker_AnyFlatpakExists_Call {
_c.Call.Return(run)
return _c
}
// CommandExists provides a mock function for the type MockAppChecker
func (_mock *MockAppChecker) CommandExists(cmd string) bool {
ret := _mock.Called(cmd)
if len(ret) == 0 {
panic("no return value specified for CommandExists")
}
var r0 bool
if returnFunc, ok := ret.Get(0).(func(string) bool); ok {
r0 = returnFunc(cmd)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_CommandExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CommandExists'
type MockAppChecker_CommandExists_Call struct {
*mock.Call
}
// CommandExists is a helper method to define mock.On call
// - cmd string
func (_e *MockAppChecker_Expecter) CommandExists(cmd any) *MockAppChecker_CommandExists_Call {
return &MockAppChecker_CommandExists_Call{Call: _e.mock.On("CommandExists", cmd)}
}
func (_c *MockAppChecker_CommandExists_Call) Run(run func(cmd string)) *MockAppChecker_CommandExists_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockAppChecker_CommandExists_Call) Return(b bool) *MockAppChecker_CommandExists_Call {
_c.Call.Return(b)
return _c
}
func (_c *MockAppChecker_CommandExists_Call) RunAndReturn(run func(cmd string) bool) *MockAppChecker_CommandExists_Call {
_c.Call.Return(run)
return _c
}
// FlatpakExists provides a mock function for the type MockAppChecker
func (_mock *MockAppChecker) FlatpakExists(name string) bool {
ret := _mock.Called(name)
if len(ret) == 0 {
panic("no return value specified for FlatpakExists")
}
var r0 bool
if returnFunc, ok := ret.Get(0).(func(string) bool); ok {
r0 = returnFunc(name)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockAppChecker_FlatpakExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FlatpakExists'
type MockAppChecker_FlatpakExists_Call struct {
*mock.Call
}
// FlatpakExists is a helper method to define mock.On call
// - name string
func (_e *MockAppChecker_Expecter) FlatpakExists(name any) *MockAppChecker_FlatpakExists_Call {
return &MockAppChecker_FlatpakExists_Call{Call: _e.mock.On("FlatpakExists", name)}
}
func (_c *MockAppChecker_FlatpakExists_Call) Run(run func(name string)) *MockAppChecker_FlatpakExists_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockAppChecker_FlatpakExists_Call) Return(b bool) *MockAppChecker_FlatpakExists_Call {
_c.Call.Return(b)
return _c
}
func (_c *MockAppChecker_FlatpakExists_Call) RunAndReturn(run func(name string) bool) *MockAppChecker_FlatpakExists_Call {
_c.Call.Return(run)
return _c
}
+139 -127
View File
@@ -1,133 +1,12 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_version package mocks_version
import mock "github.com/stretchr/testify/mock" import (
mock "github.com/stretchr/testify/mock"
// MockVersionFetcher is an autogenerated mock type for the VersionFetcher type )
type MockVersionFetcher struct {
mock.Mock
}
type MockVersionFetcher_Expecter struct {
mock *mock.Mock
}
func (_m *MockVersionFetcher) EXPECT() *MockVersionFetcher_Expecter {
return &MockVersionFetcher_Expecter{mock: &_m.Mock}
}
// GetCurrentVersion provides a mock function with given fields: dmsPath
func (_m *MockVersionFetcher) GetCurrentVersion(dmsPath string) (string, error) {
ret := _m.Called(dmsPath)
if len(ret) == 0 {
panic("no return value specified for GetCurrentVersion")
}
var r0 string
var r1 error
if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
return rf(dmsPath)
}
if rf, ok := ret.Get(0).(func(string) string); ok {
r0 = rf(dmsPath)
} else {
r0 = ret.Get(0).(string)
}
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(dmsPath)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockVersionFetcher_GetCurrentVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCurrentVersion'
type MockVersionFetcher_GetCurrentVersion_Call struct {
*mock.Call
}
// GetCurrentVersion is a helper method to define mock.On call
// - dmsPath string
func (_e *MockVersionFetcher_Expecter) GetCurrentVersion(dmsPath interface{}) *MockVersionFetcher_GetCurrentVersion_Call {
return &MockVersionFetcher_GetCurrentVersion_Call{Call: _e.mock.On("GetCurrentVersion", dmsPath)}
}
func (_c *MockVersionFetcher_GetCurrentVersion_Call) Run(run func(dmsPath string)) *MockVersionFetcher_GetCurrentVersion_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockVersionFetcher_GetCurrentVersion_Call) Return(_a0 string, _a1 error) *MockVersionFetcher_GetCurrentVersion_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockVersionFetcher_GetCurrentVersion_Call) RunAndReturn(run func(string) (string, error)) *MockVersionFetcher_GetCurrentVersion_Call {
_c.Call.Return(run)
return _c
}
// GetLatestVersion provides a mock function with given fields: dmsPath
func (_m *MockVersionFetcher) GetLatestVersion(dmsPath string) (string, error) {
ret := _m.Called(dmsPath)
if len(ret) == 0 {
panic("no return value specified for GetLatestVersion")
}
var r0 string
var r1 error
if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
return rf(dmsPath)
}
if rf, ok := ret.Get(0).(func(string) string); ok {
r0 = rf(dmsPath)
} else {
r0 = ret.Get(0).(string)
}
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(dmsPath)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockVersionFetcher_GetLatestVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestVersion'
type MockVersionFetcher_GetLatestVersion_Call struct {
*mock.Call
}
// GetLatestVersion is a helper method to define mock.On call
// - dmsPath string
func (_e *MockVersionFetcher_Expecter) GetLatestVersion(dmsPath interface{}) *MockVersionFetcher_GetLatestVersion_Call {
return &MockVersionFetcher_GetLatestVersion_Call{Call: _e.mock.On("GetLatestVersion", dmsPath)}
}
func (_c *MockVersionFetcher_GetLatestVersion_Call) Run(run func(dmsPath string)) *MockVersionFetcher_GetLatestVersion_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockVersionFetcher_GetLatestVersion_Call) Return(_a0 string, _a1 error) *MockVersionFetcher_GetLatestVersion_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockVersionFetcher_GetLatestVersion_Call) RunAndReturn(run func(string) (string, error)) *MockVersionFetcher_GetLatestVersion_Call {
_c.Call.Return(run)
return _c
}
// NewMockVersionFetcher creates a new instance of MockVersionFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // NewMockVersionFetcher creates a new instance of MockVersionFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value. // The first argument is typically a *testing.T value.
@@ -142,3 +21,136 @@ func NewMockVersionFetcher(t interface {
return mock return mock
} }
// MockVersionFetcher is an autogenerated mock type for the VersionFetcher type
type MockVersionFetcher struct {
mock.Mock
}
type MockVersionFetcher_Expecter struct {
mock *mock.Mock
}
func (_m *MockVersionFetcher) EXPECT() *MockVersionFetcher_Expecter {
return &MockVersionFetcher_Expecter{mock: &_m.Mock}
}
// GetCurrentVersion provides a mock function for the type MockVersionFetcher
func (_mock *MockVersionFetcher) GetCurrentVersion(dmsPath string) (string, error) {
ret := _mock.Called(dmsPath)
if len(ret) == 0 {
panic("no return value specified for GetCurrentVersion")
}
var r0 string
var r1 error
if returnFunc, ok := ret.Get(0).(func(string) (string, error)); ok {
return returnFunc(dmsPath)
}
if returnFunc, ok := ret.Get(0).(func(string) string); ok {
r0 = returnFunc(dmsPath)
} else {
r0 = ret.Get(0).(string)
}
if returnFunc, ok := ret.Get(1).(func(string) error); ok {
r1 = returnFunc(dmsPath)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockVersionFetcher_GetCurrentVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCurrentVersion'
type MockVersionFetcher_GetCurrentVersion_Call struct {
*mock.Call
}
// GetCurrentVersion is a helper method to define mock.On call
// - dmsPath string
func (_e *MockVersionFetcher_Expecter) GetCurrentVersion(dmsPath any) *MockVersionFetcher_GetCurrentVersion_Call {
return &MockVersionFetcher_GetCurrentVersion_Call{Call: _e.mock.On("GetCurrentVersion", dmsPath)}
}
func (_c *MockVersionFetcher_GetCurrentVersion_Call) Run(run func(dmsPath string)) *MockVersionFetcher_GetCurrentVersion_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockVersionFetcher_GetCurrentVersion_Call) Return(s string, err error) *MockVersionFetcher_GetCurrentVersion_Call {
_c.Call.Return(s, err)
return _c
}
func (_c *MockVersionFetcher_GetCurrentVersion_Call) RunAndReturn(run func(dmsPath string) (string, error)) *MockVersionFetcher_GetCurrentVersion_Call {
_c.Call.Return(run)
return _c
}
// GetLatestVersion provides a mock function for the type MockVersionFetcher
func (_mock *MockVersionFetcher) GetLatestVersion(dmsPath string) (string, error) {
ret := _mock.Called(dmsPath)
if len(ret) == 0 {
panic("no return value specified for GetLatestVersion")
}
var r0 string
var r1 error
if returnFunc, ok := ret.Get(0).(func(string) (string, error)); ok {
return returnFunc(dmsPath)
}
if returnFunc, ok := ret.Get(0).(func(string) string); ok {
r0 = returnFunc(dmsPath)
} else {
r0 = ret.Get(0).(string)
}
if returnFunc, ok := ret.Get(1).(func(string) error); ok {
r1 = returnFunc(dmsPath)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockVersionFetcher_GetLatestVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestVersion'
type MockVersionFetcher_GetLatestVersion_Call struct {
*mock.Call
}
// GetLatestVersion is a helper method to define mock.On call
// - dmsPath string
func (_e *MockVersionFetcher_Expecter) GetLatestVersion(dmsPath any) *MockVersionFetcher_GetLatestVersion_Call {
return &MockVersionFetcher_GetLatestVersion_Call{Call: _e.mock.On("GetLatestVersion", dmsPath)}
}
func (_c *MockVersionFetcher_GetLatestVersion_Call) Run(run func(dmsPath string)) *MockVersionFetcher_GetLatestVersion_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockVersionFetcher_GetLatestVersion_Call) Return(s string, err error) *MockVersionFetcher_GetLatestVersion_Call {
_c.Call.Return(s, err)
return _c
}
func (_c *MockVersionFetcher_GetLatestVersion_Call) RunAndReturn(run func(dmsPath string) (string, error)) *MockVersionFetcher_GetLatestVersion_Call {
_c.Call.Return(run)
return _c
}
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_wlclient package mocks_wlclient
import ( import (
client "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client" "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockWaylandDisplay creates a new instance of MockWaylandDisplay. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockWaylandDisplay(t interface {
mock.TestingT
Cleanup(func())
}) *MockWaylandDisplay {
mock := &MockWaylandDisplay{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockWaylandDisplay is an autogenerated mock type for the WaylandDisplay type // MockWaylandDisplay is an autogenerated mock type for the WaylandDisplay type
type MockWaylandDisplay struct { type MockWaylandDisplay struct {
mock.Mock mock.Mock
@@ -20,23 +36,22 @@ func (_m *MockWaylandDisplay) EXPECT() *MockWaylandDisplay_Expecter {
return &MockWaylandDisplay_Expecter{mock: &_m.Mock} return &MockWaylandDisplay_Expecter{mock: &_m.Mock}
} }
// Context provides a mock function with no fields // Context provides a mock function for the type MockWaylandDisplay
func (_m *MockWaylandDisplay) Context() *client.Context { func (_mock *MockWaylandDisplay) Context() *client.Context {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Context") panic("no return value specified for Context")
} }
var r0 *client.Context var r0 *client.Context
if rf, ok := ret.Get(0).(func() *client.Context); ok { if returnFunc, ok := ret.Get(0).(func() *client.Context); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*client.Context) r0 = ret.Get(0).(*client.Context)
} }
} }
return r0 return r0
} }
@@ -57,8 +72,8 @@ func (_c *MockWaylandDisplay_Context_Call) Run(run func()) *MockWaylandDisplay_C
return _c return _c
} }
func (_c *MockWaylandDisplay_Context_Call) Return(_a0 *client.Context) *MockWaylandDisplay_Context_Call { func (_c *MockWaylandDisplay_Context_Call) Return(context *client.Context) *MockWaylandDisplay_Context_Call {
_c.Call.Return(_a0) _c.Call.Return(context)
return _c return _c
} }
@@ -67,21 +82,20 @@ func (_c *MockWaylandDisplay_Context_Call) RunAndReturn(run func() *client.Conte
return _c return _c
} }
// Destroy provides a mock function with no fields // Destroy provides a mock function for the type MockWaylandDisplay
func (_m *MockWaylandDisplay) Destroy() error { func (_mock *MockWaylandDisplay) Destroy() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Destroy") panic("no return value specified for Destroy")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -102,8 +116,8 @@ func (_c *MockWaylandDisplay_Destroy_Call) Run(run func()) *MockWaylandDisplay_D
return _c return _c
} }
func (_c *MockWaylandDisplay_Destroy_Call) Return(_a0 error) *MockWaylandDisplay_Destroy_Call { func (_c *MockWaylandDisplay_Destroy_Call) Return(err error) *MockWaylandDisplay_Destroy_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -112,9 +126,9 @@ func (_c *MockWaylandDisplay_Destroy_Call) RunAndReturn(run func() error) *MockW
return _c return _c
} }
// GetRegistry provides a mock function with no fields // GetRegistry provides a mock function for the type MockWaylandDisplay
func (_m *MockWaylandDisplay) GetRegistry() (*client.Registry, error) { func (_mock *MockWaylandDisplay) GetRegistry() (*client.Registry, error) {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetRegistry") panic("no return value specified for GetRegistry")
@@ -122,23 +136,21 @@ func (_m *MockWaylandDisplay) GetRegistry() (*client.Registry, error) {
var r0 *client.Registry var r0 *client.Registry
var r1 error var r1 error
if rf, ok := ret.Get(0).(func() (*client.Registry, error)); ok { if returnFunc, ok := ret.Get(0).(func() (*client.Registry, error)); ok {
return rf() return returnFunc()
} }
if rf, ok := ret.Get(0).(func() *client.Registry); ok { if returnFunc, ok := ret.Get(0).(func() *client.Registry); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*client.Registry) r0 = ret.Get(0).(*client.Registry)
} }
} }
if returnFunc, ok := ret.Get(1).(func() error); ok {
if rf, ok := ret.Get(1).(func() error); ok { r1 = returnFunc()
r1 = rf()
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
return r0, r1 return r0, r1
} }
@@ -159,8 +171,8 @@ func (_c *MockWaylandDisplay_GetRegistry_Call) Run(run func()) *MockWaylandDispl
return _c return _c
} }
func (_c *MockWaylandDisplay_GetRegistry_Call) Return(_a0 *client.Registry, _a1 error) *MockWaylandDisplay_GetRegistry_Call { func (_c *MockWaylandDisplay_GetRegistry_Call) Return(registry *client.Registry, err error) *MockWaylandDisplay_GetRegistry_Call {
_c.Call.Return(_a0, _a1) _c.Call.Return(registry, err)
return _c return _c
} }
@@ -169,21 +181,20 @@ func (_c *MockWaylandDisplay_GetRegistry_Call) RunAndReturn(run func() (*client.
return _c return _c
} }
// Roundtrip provides a mock function with no fields // Roundtrip provides a mock function for the type MockWaylandDisplay
func (_m *MockWaylandDisplay) Roundtrip() error { func (_mock *MockWaylandDisplay) Roundtrip() error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Roundtrip") panic("no return value specified for Roundtrip")
} }
var r0 error var r0 error
if rf, ok := ret.Get(0).(func() error); ok { if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }
return r0 return r0
} }
@@ -204,8 +215,8 @@ func (_c *MockWaylandDisplay_Roundtrip_Call) Run(run func()) *MockWaylandDisplay
return _c return _c
} }
func (_c *MockWaylandDisplay_Roundtrip_Call) Return(_a0 error) *MockWaylandDisplay_Roundtrip_Call { func (_c *MockWaylandDisplay_Roundtrip_Call) Return(err error) *MockWaylandDisplay_Roundtrip_Call {
_c.Call.Return(_a0) _c.Call.Return(err)
return _c return _c
} }
@@ -213,17 +224,3 @@ func (_c *MockWaylandDisplay_Roundtrip_Call) RunAndReturn(run func() error) *Moc
_c.Call.Return(run) _c.Call.Return(run)
return _c return _c
} }
// NewMockWaylandDisplay creates a new instance of MockWaylandDisplay. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockWaylandDisplay(t interface {
mock.TestingT
Cleanup(func())
}) *MockWaylandDisplay {
mock := &MockWaylandDisplay{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -1,12 +1,28 @@
// Code generated by mockery v2.53.5. DO NOT EDIT. // Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks_wlcontext package mocks_wlcontext
import ( import (
client "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client" "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
) )
// NewMockWaylandContext creates a new instance of MockWaylandContext. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockWaylandContext(t interface {
mock.TestingT
Cleanup(func())
}) *MockWaylandContext {
mock := &MockWaylandContext{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockWaylandContext is an autogenerated mock type for the WaylandContext type // MockWaylandContext is an autogenerated mock type for the WaylandContext type
type MockWaylandContext struct { type MockWaylandContext struct {
mock.Mock mock.Mock
@@ -20,9 +36,10 @@ func (_m *MockWaylandContext) EXPECT() *MockWaylandContext_Expecter {
return &MockWaylandContext_Expecter{mock: &_m.Mock} return &MockWaylandContext_Expecter{mock: &_m.Mock}
} }
// Close provides a mock function with no fields // Close provides a mock function for the type MockWaylandContext
func (_m *MockWaylandContext) Close() { func (_mock *MockWaylandContext) Close() {
_m.Called() _mock.Called()
return
} }
// MockWaylandContext_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' // MockWaylandContext_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
@@ -52,23 +69,22 @@ func (_c *MockWaylandContext_Close_Call) RunAndReturn(run func()) *MockWaylandCo
return _c return _c
} }
// Display provides a mock function with no fields // Display provides a mock function for the type MockWaylandContext
func (_m *MockWaylandContext) Display() *client.Display { func (_mock *MockWaylandContext) Display() *client.Display {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for Display") panic("no return value specified for Display")
} }
var r0 *client.Display var r0 *client.Display
if rf, ok := ret.Get(0).(func() *client.Display); ok { if returnFunc, ok := ret.Get(0).(func() *client.Display); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*client.Display) r0 = ret.Get(0).(*client.Display)
} }
} }
return r0 return r0
} }
@@ -89,8 +105,8 @@ func (_c *MockWaylandContext_Display_Call) Run(run func()) *MockWaylandContext_D
return _c return _c
} }
func (_c *MockWaylandContext_Display_Call) Return(_a0 *client.Display) *MockWaylandContext_Display_Call { func (_c *MockWaylandContext_Display_Call) Return(display *client.Display) *MockWaylandContext_Display_Call {
_c.Call.Return(_a0) _c.Call.Return(display)
return _c return _c
} }
@@ -99,23 +115,22 @@ func (_c *MockWaylandContext_Display_Call) RunAndReturn(run func() *client.Displ
return _c return _c
} }
// FatalError provides a mock function with no fields // FatalError provides a mock function for the type MockWaylandContext
func (_m *MockWaylandContext) FatalError() <-chan error { func (_mock *MockWaylandContext) FatalError() <-chan error {
ret := _m.Called() ret := _mock.Called()
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for FatalError") panic("no return value specified for FatalError")
} }
var r0 <-chan error var r0 <-chan error
if rf, ok := ret.Get(0).(func() <-chan error); ok { if returnFunc, ok := ret.Get(0).(func() <-chan error); ok {
r0 = rf() r0 = returnFunc()
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(<-chan error) r0 = ret.Get(0).(<-chan error)
} }
} }
return r0 return r0
} }
@@ -136,8 +151,8 @@ func (_c *MockWaylandContext_FatalError_Call) Run(run func()) *MockWaylandContex
return _c return _c
} }
func (_c *MockWaylandContext_FatalError_Call) Return(_a0 <-chan error) *MockWaylandContext_FatalError_Call { func (_c *MockWaylandContext_FatalError_Call) Return(errCh <-chan error) *MockWaylandContext_FatalError_Call {
_c.Call.Return(_a0) _c.Call.Return(errCh)
return _c return _c
} }
@@ -146,9 +161,10 @@ func (_c *MockWaylandContext_FatalError_Call) RunAndReturn(run func() <-chan err
return _c return _c
} }
// Post provides a mock function with given fields: fn // Post provides a mock function for the type MockWaylandContext
func (_m *MockWaylandContext) Post(fn func()) { func (_mock *MockWaylandContext) Post(fn func()) {
_m.Called(fn) _mock.Called(fn)
return
} }
// MockWaylandContext_Post_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Post' // MockWaylandContext_Post_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Post'
@@ -158,13 +174,19 @@ type MockWaylandContext_Post_Call struct {
// Post is a helper method to define mock.On call // Post is a helper method to define mock.On call
// - fn func() // - fn func()
func (_e *MockWaylandContext_Expecter) Post(fn interface{}) *MockWaylandContext_Post_Call { func (_e *MockWaylandContext_Expecter) Post(fn any) *MockWaylandContext_Post_Call {
return &MockWaylandContext_Post_Call{Call: _e.mock.On("Post", fn)} return &MockWaylandContext_Post_Call{Call: _e.mock.On("Post", fn)}
} }
func (_c *MockWaylandContext_Post_Call) Run(run func(fn func())) *MockWaylandContext_Post_Call { func (_c *MockWaylandContext_Post_Call) Run(run func(fn func())) *MockWaylandContext_Post_Call {
_c.Call.Run(func(args mock.Arguments) { _c.Call.Run(func(args mock.Arguments) {
run(args[0].(func())) var arg0 func()
if args[0] != nil {
arg0 = args[0].(func())
}
run(
arg0,
)
}) })
return _c return _c
} }
@@ -174,14 +196,15 @@ func (_c *MockWaylandContext_Post_Call) Return() *MockWaylandContext_Post_Call {
return _c return _c
} }
func (_c *MockWaylandContext_Post_Call) RunAndReturn(run func(func())) *MockWaylandContext_Post_Call { func (_c *MockWaylandContext_Post_Call) RunAndReturn(run func(fn func())) *MockWaylandContext_Post_Call {
_c.Run(run) _c.Run(run)
return _c return _c
} }
// Start provides a mock function with no fields // Start provides a mock function for the type MockWaylandContext
func (_m *MockWaylandContext) Start() { func (_mock *MockWaylandContext) Start() {
_m.Called() _mock.Called()
return
} }
// MockWaylandContext_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' // MockWaylandContext_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start'
@@ -210,17 +233,3 @@ func (_c *MockWaylandContext_Start_Call) RunAndReturn(run func()) *MockWaylandCo
_c.Run(run) _c.Run(run)
return _c return _c
} }
// NewMockWaylandContext creates a new instance of MockWaylandContext. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockWaylandContext(t interface {
mock.TestingT
Cleanup(func())
}) *MockWaylandContext {
mock := &MockWaylandContext{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
+3
View File
@@ -499,6 +499,9 @@ func buildManagedLockscreenU2FPamContent() string {
b.WriteString("#%PAM-1.0\n") b.WriteString("#%PAM-1.0\n")
b.WriteString(LockscreenU2FPamManagedBlockStart + "\n") b.WriteString(LockscreenU2FPamManagedBlockStart + "\n")
b.WriteString("auth required pam_u2f.so cue nouserok timeout=10\n") b.WriteString("auth required pam_u2f.so cue nouserok timeout=10\n")
b.WriteString("account required pam_permit.so\n")
b.WriteString("password required pam_deny.so\n")
b.WriteString("session required pam_permit.so\n")
b.WriteString(LockscreenU2FPamManagedBlockEnd + "\n") b.WriteString(LockscreenU2FPamManagedBlockEnd + "\n")
return b.String() return b.String()
} }
-791
View File
@@ -1,791 +0,0 @@
// Generated by go-wayland-scanner
// https://github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/cmd/go-wayland-scanner
// XML file : internal/proto/xml/dwl-ipc-unstable-v2.xml
//
// dwl_ipc_unstable_v2 Protocol Copyright:
package dwl_ipc
import "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
// ZdwlIpcManagerV2InterfaceName is the name of the interface as it appears in the [client.Registry].
// It can be used to match the [client.RegistryGlobalEvent.Interface] in the
// [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies.
const ZdwlIpcManagerV2InterfaceName = "zdwl_ipc_manager_v2"
// ZdwlIpcManagerV2 : manage dwl state
//
// This interface is exposed as a global in wl_registry.
//
// Clients can use this interface to get a dwl_ipc_output.
// After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
// The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
type ZdwlIpcManagerV2 struct {
client.BaseProxy
tagsHandler ZdwlIpcManagerV2TagsHandlerFunc
layoutHandler ZdwlIpcManagerV2LayoutHandlerFunc
}
// NewZdwlIpcManagerV2 : manage dwl state
//
// This interface is exposed as a global in wl_registry.
//
// Clients can use this interface to get a dwl_ipc_output.
// After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
// The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
func NewZdwlIpcManagerV2(ctx *client.Context) *ZdwlIpcManagerV2 {
zdwlIpcManagerV2 := &ZdwlIpcManagerV2{}
ctx.Register(zdwlIpcManagerV2)
return zdwlIpcManagerV2
}
// Release : release dwl_ipc_manager
//
// Indicates that the client will not the dwl_ipc_manager object anymore.
// Objects created through this instance are not affected.
func (i *ZdwlIpcManagerV2) Release() error {
defer i.MarkZombie()
const opcode = 0
const _reqBufLen = 8
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return err
}
// GetOutput : get a dwl_ipc_outout for a wl_output
//
// Get a dwl_ipc_outout for the specified wl_output.
func (i *ZdwlIpcManagerV2) GetOutput(output *client.Output) (*ZdwlIpcOutputV2, error) {
id := NewZdwlIpcOutputV2(i.Context())
const opcode = 1
const _reqBufLen = 8 + 4 + 4
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
client.PutUint32(_reqBuf[l:l+4], id.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], output.ID())
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return id, err
}
// ZdwlIpcManagerV2TagsEvent : Announces tag amount
//
// This event is sent after binding.
// A roundtrip after binding guarantees the client recieved all tags.
type ZdwlIpcManagerV2TagsEvent struct {
Amount uint32
}
type ZdwlIpcManagerV2TagsHandlerFunc func(ZdwlIpcManagerV2TagsEvent)
// SetTagsHandler : sets handler for ZdwlIpcManagerV2TagsEvent
func (i *ZdwlIpcManagerV2) SetTagsHandler(f ZdwlIpcManagerV2TagsHandlerFunc) {
i.tagsHandler = f
}
// ZdwlIpcManagerV2LayoutEvent : Announces a layout
//
// This event is sent after binding.
// A roundtrip after binding guarantees the client recieved all layouts.
type ZdwlIpcManagerV2LayoutEvent struct {
Name string
}
type ZdwlIpcManagerV2LayoutHandlerFunc func(ZdwlIpcManagerV2LayoutEvent)
// SetLayoutHandler : sets handler for ZdwlIpcManagerV2LayoutEvent
func (i *ZdwlIpcManagerV2) SetLayoutHandler(f ZdwlIpcManagerV2LayoutHandlerFunc) {
i.layoutHandler = f
}
func (i *ZdwlIpcManagerV2) Dispatch(opcode uint32, fd int, data []byte) {
switch opcode {
case 0:
if i.tagsHandler == nil {
return
}
var e ZdwlIpcManagerV2TagsEvent
l := 0
e.Amount = client.Uint32(data[l : l+4])
l += 4
i.tagsHandler(e)
case 1:
if i.layoutHandler == nil {
return
}
var e ZdwlIpcManagerV2LayoutEvent
l := 0
nameLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.Name = client.String(data[l : l+nameLen])
l += nameLen
i.layoutHandler(e)
}
}
// ZdwlIpcOutputV2InterfaceName is the name of the interface as it appears in the [client.Registry].
// It can be used to match the [client.RegistryGlobalEvent.Interface] in the
// [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies.
const ZdwlIpcOutputV2InterfaceName = "zdwl_ipc_output_v2"
// ZdwlIpcOutputV2 : control dwl output
//
// Observe and control a dwl output.
//
// Events are double-buffered:
// Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
//
// Request are not double-buffered:
// The compositor will update immediately upon request.
type ZdwlIpcOutputV2 struct {
client.BaseProxy
toggleVisibilityHandler ZdwlIpcOutputV2ToggleVisibilityHandlerFunc
activeHandler ZdwlIpcOutputV2ActiveHandlerFunc
tagHandler ZdwlIpcOutputV2TagHandlerFunc
layoutHandler ZdwlIpcOutputV2LayoutHandlerFunc
titleHandler ZdwlIpcOutputV2TitleHandlerFunc
appidHandler ZdwlIpcOutputV2AppidHandlerFunc
layoutSymbolHandler ZdwlIpcOutputV2LayoutSymbolHandlerFunc
frameHandler ZdwlIpcOutputV2FrameHandlerFunc
fullscreenHandler ZdwlIpcOutputV2FullscreenHandlerFunc
floatingHandler ZdwlIpcOutputV2FloatingHandlerFunc
xHandler ZdwlIpcOutputV2XHandlerFunc
yHandler ZdwlIpcOutputV2YHandlerFunc
widthHandler ZdwlIpcOutputV2WidthHandlerFunc
heightHandler ZdwlIpcOutputV2HeightHandlerFunc
lastLayerHandler ZdwlIpcOutputV2LastLayerHandlerFunc
kbLayoutHandler ZdwlIpcOutputV2KbLayoutHandlerFunc
keymodeHandler ZdwlIpcOutputV2KeymodeHandlerFunc
scalefactorHandler ZdwlIpcOutputV2ScalefactorHandlerFunc
}
// NewZdwlIpcOutputV2 : control dwl output
//
// Observe and control a dwl output.
//
// Events are double-buffered:
// Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
//
// Request are not double-buffered:
// The compositor will update immediately upon request.
func NewZdwlIpcOutputV2(ctx *client.Context) *ZdwlIpcOutputV2 {
zdwlIpcOutputV2 := &ZdwlIpcOutputV2{}
ctx.Register(zdwlIpcOutputV2)
return zdwlIpcOutputV2
}
// Release : release dwl_ipc_outout
//
// Indicates to that the client no longer needs this dwl_ipc_output.
func (i *ZdwlIpcOutputV2) Release() error {
defer i.MarkZombie()
const opcode = 0
const _reqBufLen = 8
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return err
}
// SetTags : Set the active tags of this output
//
// tagmask: bitmask of the tags that should be set.
// toggleTagset: toggle the selected tagset, zero for invalid, nonzero for valid.
func (i *ZdwlIpcOutputV2) SetTags(tagmask, toggleTagset uint32) error {
const opcode = 1
const _reqBufLen = 8 + 4 + 4
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(tagmask))
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(toggleTagset))
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return err
}
// SetClientTags : Set the tags of the focused client.
//
// The tags are updated as follows:
// new_tags = (current_tags AND and_tags) XOR xor_tags
func (i *ZdwlIpcOutputV2) SetClientTags(andTags, xorTags uint32) error {
const opcode = 2
const _reqBufLen = 8 + 4 + 4
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(andTags))
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(xorTags))
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return err
}
// SetLayout : Set the layout of this output
//
// index: index of a layout recieved by dwl_ipc_manager.layout
func (i *ZdwlIpcOutputV2) SetLayout(index uint32) error {
const opcode = 3
const _reqBufLen = 8 + 4
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(index))
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return err
}
// Quit : Quit mango
// This request allows clients to instruct the compositor to quit mango.
func (i *ZdwlIpcOutputV2) Quit() error {
const opcode = 4
const _reqBufLen = 8
var _reqBuf [_reqBufLen]byte
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
err := i.Context().WriteMsg(_reqBuf[:], nil)
return err
}
// SendDispatch : Set the active tags of this output
//
// dispatch: dispatch name.
// arg1: arg1.
// arg2: arg2.
// arg3: arg3.
// arg4: arg4.
// arg5: arg5.
func (i *ZdwlIpcOutputV2) SendDispatch(dispatch, arg1, arg2, arg3, arg4, arg5 string) error {
const opcode = 5
dispatchLen := client.PaddedLen(len(dispatch) + 1)
arg1Len := client.PaddedLen(len(arg1) + 1)
arg2Len := client.PaddedLen(len(arg2) + 1)
arg3Len := client.PaddedLen(len(arg3) + 1)
arg4Len := client.PaddedLen(len(arg4) + 1)
arg5Len := client.PaddedLen(len(arg5) + 1)
_reqBufLen := 8 + (4 + dispatchLen) + (4 + arg1Len) + (4 + arg2Len) + (4 + arg3Len) + (4 + arg4Len) + (4 + arg5Len)
_reqBuf := make([]byte, _reqBufLen)
l := 0
client.PutUint32(_reqBuf[l:4], i.ID())
l += 4
client.PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
l += 4
client.PutString(_reqBuf[l:l+(4+dispatchLen)], dispatch)
l += (4 + dispatchLen)
client.PutString(_reqBuf[l:l+(4+arg1Len)], arg1)
l += (4 + arg1Len)
client.PutString(_reqBuf[l:l+(4+arg2Len)], arg2)
l += (4 + arg2Len)
client.PutString(_reqBuf[l:l+(4+arg3Len)], arg3)
l += (4 + arg3Len)
client.PutString(_reqBuf[l:l+(4+arg4Len)], arg4)
l += (4 + arg4Len)
client.PutString(_reqBuf[l:l+(4+arg5Len)], arg5)
l += (4 + arg5Len)
err := i.Context().WriteMsg(_reqBuf, nil)
return err
}
type ZdwlIpcOutputV2TagState uint32
// ZdwlIpcOutputV2TagState :
const (
// ZdwlIpcOutputV2TagStateNone : no state
ZdwlIpcOutputV2TagStateNone ZdwlIpcOutputV2TagState = 0
// ZdwlIpcOutputV2TagStateActive : tag is active
ZdwlIpcOutputV2TagStateActive ZdwlIpcOutputV2TagState = 1
// ZdwlIpcOutputV2TagStateUrgent : tag has at least one urgent client
ZdwlIpcOutputV2TagStateUrgent ZdwlIpcOutputV2TagState = 2
)
func (e ZdwlIpcOutputV2TagState) Name() string {
switch e {
case ZdwlIpcOutputV2TagStateNone:
return "none"
case ZdwlIpcOutputV2TagStateActive:
return "active"
case ZdwlIpcOutputV2TagStateUrgent:
return "urgent"
default:
return ""
}
}
func (e ZdwlIpcOutputV2TagState) Value() string {
switch e {
case ZdwlIpcOutputV2TagStateNone:
return "0"
case ZdwlIpcOutputV2TagStateActive:
return "1"
case ZdwlIpcOutputV2TagStateUrgent:
return "2"
default:
return ""
}
}
func (e ZdwlIpcOutputV2TagState) String() string {
return e.Name() + "=" + e.Value()
}
// ZdwlIpcOutputV2ToggleVisibilityEvent : Toggle client visibilty
//
// Indicates the client should hide or show themselves.
// If the client is visible then hide, if hidden then show.
type ZdwlIpcOutputV2ToggleVisibilityEvent struct{}
type ZdwlIpcOutputV2ToggleVisibilityHandlerFunc func(ZdwlIpcOutputV2ToggleVisibilityEvent)
// SetToggleVisibilityHandler : sets handler for ZdwlIpcOutputV2ToggleVisibilityEvent
func (i *ZdwlIpcOutputV2) SetToggleVisibilityHandler(f ZdwlIpcOutputV2ToggleVisibilityHandlerFunc) {
i.toggleVisibilityHandler = f
}
// ZdwlIpcOutputV2ActiveEvent : Update the selected output.
//
// Indicates if the output is active. Zero is invalid, nonzero is valid.
type ZdwlIpcOutputV2ActiveEvent struct {
Active uint32
}
type ZdwlIpcOutputV2ActiveHandlerFunc func(ZdwlIpcOutputV2ActiveEvent)
// SetActiveHandler : sets handler for ZdwlIpcOutputV2ActiveEvent
func (i *ZdwlIpcOutputV2) SetActiveHandler(f ZdwlIpcOutputV2ActiveHandlerFunc) {
i.activeHandler = f
}
// ZdwlIpcOutputV2TagEvent : Update the state of a tag.
//
// Indicates that a tag has been updated.
type ZdwlIpcOutputV2TagEvent struct {
Tag uint32
State uint32
Clients uint32
Focused uint32
}
type ZdwlIpcOutputV2TagHandlerFunc func(ZdwlIpcOutputV2TagEvent)
// SetTagHandler : sets handler for ZdwlIpcOutputV2TagEvent
func (i *ZdwlIpcOutputV2) SetTagHandler(f ZdwlIpcOutputV2TagHandlerFunc) {
i.tagHandler = f
}
// ZdwlIpcOutputV2LayoutEvent : Update the layout.
//
// Indicates a new layout is selected.
type ZdwlIpcOutputV2LayoutEvent struct {
Layout uint32
}
type ZdwlIpcOutputV2LayoutHandlerFunc func(ZdwlIpcOutputV2LayoutEvent)
// SetLayoutHandler : sets handler for ZdwlIpcOutputV2LayoutEvent
func (i *ZdwlIpcOutputV2) SetLayoutHandler(f ZdwlIpcOutputV2LayoutHandlerFunc) {
i.layoutHandler = f
}
// ZdwlIpcOutputV2TitleEvent : Update the title.
//
// Indicates the title has changed.
type ZdwlIpcOutputV2TitleEvent struct {
Title string
}
type ZdwlIpcOutputV2TitleHandlerFunc func(ZdwlIpcOutputV2TitleEvent)
// SetTitleHandler : sets handler for ZdwlIpcOutputV2TitleEvent
func (i *ZdwlIpcOutputV2) SetTitleHandler(f ZdwlIpcOutputV2TitleHandlerFunc) {
i.titleHandler = f
}
// ZdwlIpcOutputV2AppidEvent : Update the appid.
//
// Indicates the appid has changed.
type ZdwlIpcOutputV2AppidEvent struct {
Appid string
}
type ZdwlIpcOutputV2AppidHandlerFunc func(ZdwlIpcOutputV2AppidEvent)
// SetAppidHandler : sets handler for ZdwlIpcOutputV2AppidEvent
func (i *ZdwlIpcOutputV2) SetAppidHandler(f ZdwlIpcOutputV2AppidHandlerFunc) {
i.appidHandler = f
}
// ZdwlIpcOutputV2LayoutSymbolEvent : Update the current layout symbol
//
// Indicates the layout has changed. Since layout symbols are dynamic.
// As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
// You can ignore the zdwl_ipc_output.layout event.
type ZdwlIpcOutputV2LayoutSymbolEvent struct {
Layout string
}
type ZdwlIpcOutputV2LayoutSymbolHandlerFunc func(ZdwlIpcOutputV2LayoutSymbolEvent)
// SetLayoutSymbolHandler : sets handler for ZdwlIpcOutputV2LayoutSymbolEvent
func (i *ZdwlIpcOutputV2) SetLayoutSymbolHandler(f ZdwlIpcOutputV2LayoutSymbolHandlerFunc) {
i.layoutSymbolHandler = f
}
// ZdwlIpcOutputV2FrameEvent : The update sequence is done.
//
// Indicates that a sequence of status updates have finished and the client should redraw.
type ZdwlIpcOutputV2FrameEvent struct{}
type ZdwlIpcOutputV2FrameHandlerFunc func(ZdwlIpcOutputV2FrameEvent)
// SetFrameHandler : sets handler for ZdwlIpcOutputV2FrameEvent
func (i *ZdwlIpcOutputV2) SetFrameHandler(f ZdwlIpcOutputV2FrameHandlerFunc) {
i.frameHandler = f
}
// ZdwlIpcOutputV2FullscreenEvent : Update fullscreen status
//
// Indicates if the selected client on this output is fullscreen.
type ZdwlIpcOutputV2FullscreenEvent struct {
IsFullscreen uint32
}
type ZdwlIpcOutputV2FullscreenHandlerFunc func(ZdwlIpcOutputV2FullscreenEvent)
// SetFullscreenHandler : sets handler for ZdwlIpcOutputV2FullscreenEvent
func (i *ZdwlIpcOutputV2) SetFullscreenHandler(f ZdwlIpcOutputV2FullscreenHandlerFunc) {
i.fullscreenHandler = f
}
// ZdwlIpcOutputV2FloatingEvent : Update the floating status
//
// Indicates if the selected client on this output is floating.
type ZdwlIpcOutputV2FloatingEvent struct {
IsFloating uint32
}
type ZdwlIpcOutputV2FloatingHandlerFunc func(ZdwlIpcOutputV2FloatingEvent)
// SetFloatingHandler : sets handler for ZdwlIpcOutputV2FloatingEvent
func (i *ZdwlIpcOutputV2) SetFloatingHandler(f ZdwlIpcOutputV2FloatingHandlerFunc) {
i.floatingHandler = f
}
// ZdwlIpcOutputV2XEvent : Update the x coordinates
//
// Indicates if x coordinates of the selected client.
type ZdwlIpcOutputV2XEvent struct {
X int32
}
type ZdwlIpcOutputV2XHandlerFunc func(ZdwlIpcOutputV2XEvent)
// SetXHandler : sets handler for ZdwlIpcOutputV2XEvent
func (i *ZdwlIpcOutputV2) SetXHandler(f ZdwlIpcOutputV2XHandlerFunc) {
i.xHandler = f
}
// ZdwlIpcOutputV2YEvent : Update the y coordinates
//
// Indicates if y coordinates of the selected client.
type ZdwlIpcOutputV2YEvent struct {
Y int32
}
type ZdwlIpcOutputV2YHandlerFunc func(ZdwlIpcOutputV2YEvent)
// SetYHandler : sets handler for ZdwlIpcOutputV2YEvent
func (i *ZdwlIpcOutputV2) SetYHandler(f ZdwlIpcOutputV2YHandlerFunc) {
i.yHandler = f
}
// ZdwlIpcOutputV2WidthEvent : Update the width
//
// Indicates if width of the selected client.
type ZdwlIpcOutputV2WidthEvent struct {
Width int32
}
type ZdwlIpcOutputV2WidthHandlerFunc func(ZdwlIpcOutputV2WidthEvent)
// SetWidthHandler : sets handler for ZdwlIpcOutputV2WidthEvent
func (i *ZdwlIpcOutputV2) SetWidthHandler(f ZdwlIpcOutputV2WidthHandlerFunc) {
i.widthHandler = f
}
// ZdwlIpcOutputV2HeightEvent : Update the height
//
// Indicates if height of the selected client.
type ZdwlIpcOutputV2HeightEvent struct {
Height int32
}
type ZdwlIpcOutputV2HeightHandlerFunc func(ZdwlIpcOutputV2HeightEvent)
// SetHeightHandler : sets handler for ZdwlIpcOutputV2HeightEvent
func (i *ZdwlIpcOutputV2) SetHeightHandler(f ZdwlIpcOutputV2HeightHandlerFunc) {
i.heightHandler = f
}
// ZdwlIpcOutputV2LastLayerEvent : last map layer.
//
// last map layer.
type ZdwlIpcOutputV2LastLayerEvent struct {
LastLayer string
}
type ZdwlIpcOutputV2LastLayerHandlerFunc func(ZdwlIpcOutputV2LastLayerEvent)
// SetLastLayerHandler : sets handler for ZdwlIpcOutputV2LastLayerEvent
func (i *ZdwlIpcOutputV2) SetLastLayerHandler(f ZdwlIpcOutputV2LastLayerHandlerFunc) {
i.lastLayerHandler = f
}
// ZdwlIpcOutputV2KbLayoutEvent : current keyboard layout.
//
// current keyboard layout.
type ZdwlIpcOutputV2KbLayoutEvent struct {
KbLayout string
}
type ZdwlIpcOutputV2KbLayoutHandlerFunc func(ZdwlIpcOutputV2KbLayoutEvent)
// SetKbLayoutHandler : sets handler for ZdwlIpcOutputV2KbLayoutEvent
func (i *ZdwlIpcOutputV2) SetKbLayoutHandler(f ZdwlIpcOutputV2KbLayoutHandlerFunc) {
i.kbLayoutHandler = f
}
// ZdwlIpcOutputV2KeymodeEvent : current keybind mode.
//
// current keybind mode.
type ZdwlIpcOutputV2KeymodeEvent struct {
Keymode string
}
type ZdwlIpcOutputV2KeymodeHandlerFunc func(ZdwlIpcOutputV2KeymodeEvent)
// SetKeymodeHandler : sets handler for ZdwlIpcOutputV2KeymodeEvent
func (i *ZdwlIpcOutputV2) SetKeymodeHandler(f ZdwlIpcOutputV2KeymodeHandlerFunc) {
i.keymodeHandler = f
}
// ZdwlIpcOutputV2ScalefactorEvent : scale factor of monitor.
//
// scale factor of monitor.
type ZdwlIpcOutputV2ScalefactorEvent struct {
Scalefactor uint32
}
type ZdwlIpcOutputV2ScalefactorHandlerFunc func(ZdwlIpcOutputV2ScalefactorEvent)
// SetScalefactorHandler : sets handler for ZdwlIpcOutputV2ScalefactorEvent
func (i *ZdwlIpcOutputV2) SetScalefactorHandler(f ZdwlIpcOutputV2ScalefactorHandlerFunc) {
i.scalefactorHandler = f
}
func (i *ZdwlIpcOutputV2) Dispatch(opcode uint32, fd int, data []byte) {
switch opcode {
case 0:
if i.toggleVisibilityHandler == nil {
return
}
var e ZdwlIpcOutputV2ToggleVisibilityEvent
i.toggleVisibilityHandler(e)
case 1:
if i.activeHandler == nil {
return
}
var e ZdwlIpcOutputV2ActiveEvent
l := 0
e.Active = client.Uint32(data[l : l+4])
l += 4
i.activeHandler(e)
case 2:
if i.tagHandler == nil {
return
}
var e ZdwlIpcOutputV2TagEvent
l := 0
e.Tag = client.Uint32(data[l : l+4])
l += 4
e.State = client.Uint32(data[l : l+4])
l += 4
e.Clients = client.Uint32(data[l : l+4])
l += 4
e.Focused = client.Uint32(data[l : l+4])
l += 4
i.tagHandler(e)
case 3:
if i.layoutHandler == nil {
return
}
var e ZdwlIpcOutputV2LayoutEvent
l := 0
e.Layout = client.Uint32(data[l : l+4])
l += 4
i.layoutHandler(e)
case 4:
if i.titleHandler == nil {
return
}
var e ZdwlIpcOutputV2TitleEvent
l := 0
titleLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.Title = client.String(data[l : l+titleLen])
l += titleLen
i.titleHandler(e)
case 5:
if i.appidHandler == nil {
return
}
var e ZdwlIpcOutputV2AppidEvent
l := 0
appidLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.Appid = client.String(data[l : l+appidLen])
l += appidLen
i.appidHandler(e)
case 6:
if i.layoutSymbolHandler == nil {
return
}
var e ZdwlIpcOutputV2LayoutSymbolEvent
l := 0
layoutLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.Layout = client.String(data[l : l+layoutLen])
l += layoutLen
i.layoutSymbolHandler(e)
case 7:
if i.frameHandler == nil {
return
}
var e ZdwlIpcOutputV2FrameEvent
i.frameHandler(e)
case 8:
if i.fullscreenHandler == nil {
return
}
var e ZdwlIpcOutputV2FullscreenEvent
l := 0
e.IsFullscreen = client.Uint32(data[l : l+4])
l += 4
i.fullscreenHandler(e)
case 9:
if i.floatingHandler == nil {
return
}
var e ZdwlIpcOutputV2FloatingEvent
l := 0
e.IsFloating = client.Uint32(data[l : l+4])
l += 4
i.floatingHandler(e)
case 10:
if i.xHandler == nil {
return
}
var e ZdwlIpcOutputV2XEvent
l := 0
e.X = int32(client.Uint32(data[l : l+4]))
l += 4
i.xHandler(e)
case 11:
if i.yHandler == nil {
return
}
var e ZdwlIpcOutputV2YEvent
l := 0
e.Y = int32(client.Uint32(data[l : l+4]))
l += 4
i.yHandler(e)
case 12:
if i.widthHandler == nil {
return
}
var e ZdwlIpcOutputV2WidthEvent
l := 0
e.Width = int32(client.Uint32(data[l : l+4]))
l += 4
i.widthHandler(e)
case 13:
if i.heightHandler == nil {
return
}
var e ZdwlIpcOutputV2HeightEvent
l := 0
e.Height = int32(client.Uint32(data[l : l+4]))
l += 4
i.heightHandler(e)
case 14:
if i.lastLayerHandler == nil {
return
}
var e ZdwlIpcOutputV2LastLayerEvent
l := 0
lastLayerLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.LastLayer = client.String(data[l : l+lastLayerLen])
l += lastLayerLen
i.lastLayerHandler(e)
case 15:
if i.kbLayoutHandler == nil {
return
}
var e ZdwlIpcOutputV2KbLayoutEvent
l := 0
kbLayoutLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.KbLayout = client.String(data[l : l+kbLayoutLen])
l += kbLayoutLen
i.kbLayoutHandler(e)
case 16:
if i.keymodeHandler == nil {
return
}
var e ZdwlIpcOutputV2KeymodeEvent
l := 0
keymodeLen := client.PaddedLen(int(client.Uint32(data[l : l+4])))
l += 4
e.Keymode = client.String(data[l : l+keymodeLen])
l += keymodeLen
i.keymodeHandler(e)
case 17:
if i.scalefactorHandler == nil {
return
}
var e ZdwlIpcOutputV2ScalefactorEvent
l := 0
e.Scalefactor = client.Uint32(data[l : l+4])
l += 4
i.scalefactorHandler(e)
}
}
@@ -0,0 +1,22 @@
package qmlchecks
import (
"os"
"strings"
"testing"
)
func TestGreeterRememberLastSessionFallsBackToDesktopID(t *testing.T) {
data, err := os.ReadFile("../../../quickshell/Modules/Greetd/GreeterContent.qml")
if err != nil {
t.Fatalf("read greeter QML: %v", err)
}
content := string(data)
if !strings.Contains(content, "GreetdMemory.lastSessionDesktopId || desktopIdFromPath(GreetdMemory.lastSessionId)") {
t.Fatalf("remembered greeter sessions should derive a desktop id from legacy absolute session paths")
}
if !strings.Contains(content, "GreeterState.sessionDesktopIds[i] === savedDesktopId") {
t.Fatalf("remembered greeter sessions should match current sessions by desktop id")
}
}
@@ -0,0 +1,25 @@
package qmlchecks
import (
"os"
"regexp"
"strings"
"testing"
)
func TestLockScreenPasswordFieldBypassesTextInputIME(t *testing.T) {
data, err := os.ReadFile("../../../quickshell/Modules/Lock/LockScreenContent.qml")
if err != nil {
t.Fatalf("read lock screen QML: %v", err)
}
content := string(data)
textInputPasswordField := regexp.MustCompile(`(?s)TextInput\s*\{[^{}]*id:\s*passwordField`)
if textInputPasswordField.MatchString(content) {
t.Fatalf("passwordField must not be a TextInput because TextInput can route physical keyboard input through IME")
}
if !strings.Contains(content, "Keys.onPressed") || !strings.Contains(content, "event.text") {
t.Fatalf("passwordField should handle physical key text manually instead of relying on a text input control")
}
}
+99 -317
View File
@@ -6,7 +6,6 @@ import (
"os" "os"
"os/exec" "os/exec"
"github.com/AvengeMedia/DankMaterialShell/core/internal/proto/dwl_ipc"
"github.com/AvengeMedia/DankMaterialShell/core/internal/proto/wlr_output_management" "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/wlr_output_management"
wlhelpers "github.com/AvengeMedia/DankMaterialShell/core/internal/wayland/client" wlhelpers "github.com/AvengeMedia/DankMaterialShell/core/internal/wayland/client"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client" "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
@@ -19,9 +18,9 @@ const (
CompositorHyprland CompositorHyprland
CompositorSway CompositorSway
CompositorNiri CompositorNiri
CompositorDWL
CompositorScroll CompositorScroll
CompositorMiracle CompositorMiracle
CompositorMango
) )
var detectedCompositor Compositor = -1 var detectedCompositor Compositor = -1
@@ -36,8 +35,14 @@ func DetectCompositor() Compositor {
swaySocket := os.Getenv("SWAYSOCK") swaySocket := os.Getenv("SWAYSOCK")
scrollSocket := os.Getenv("SCROLLSOCK") scrollSocket := os.Getenv("SCROLLSOCK")
miracleSocket := os.Getenv("MIRACLESOCK") miracleSocket := os.Getenv("MIRACLESOCK")
mangoSocket := os.Getenv("MANGO_INSTANCE_SIGNATURE")
switch { switch {
case mangoSocket != "":
if _, err := os.Stat(mangoSocket); err == nil {
detectedCompositor = CompositorMango
return detectedCompositor
}
case niriSocket != "": case niriSocket != "":
if _, err := os.Stat(niriSocket); err == nil { if _, err := os.Stat(niriSocket); err == nil {
detectedCompositor = CompositorNiri detectedCompositor = CompositorNiri
@@ -63,46 +68,10 @@ func DetectCompositor() Compositor {
return detectedCompositor return detectedCompositor
} }
if detectDWLProtocol() {
detectedCompositor = CompositorDWL
return detectedCompositor
}
detectedCompositor = CompositorUnknown detectedCompositor = CompositorUnknown
return detectedCompositor return detectedCompositor
} }
func detectDWLProtocol() bool {
display, err := client.Connect("")
if err != nil {
return false
}
ctx := display.Context()
defer ctx.Close()
registry, err := display.GetRegistry()
if err != nil {
return false
}
found := false
registry.SetGlobalHandler(func(e client.RegistryGlobalEvent) {
if e.Interface == dwl_ipc.ZdwlIpcManagerV2InterfaceName {
found = true
}
})
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
return false
}
return found
}
func SetCompositorDWL() {
detectedCompositor = CompositorDWL
}
type WindowGeometry struct { type WindowGeometry struct {
X int32 X int32
Y int32 Y int32
@@ -112,17 +81,16 @@ type WindowGeometry struct {
Scale float64 Scale float64
OutputX int32 OutputX int32
OutputY int32 OutputY int32
OutputTransform int32
} }
func GetActiveWindow() (*WindowGeometry, error) { func GetActiveWindow() (*WindowGeometry, error) {
switch DetectCompositor() { switch DetectCompositor() {
case CompositorHyprland: case CompositorHyprland:
return getHyprlandActiveWindow() return getHyprlandActiveWindow()
case CompositorDWL: case CompositorMango:
return getDWLActiveWindow() return getMangoActiveWindow()
default: default:
return nil, fmt.Errorf("window capture requires Hyprland or DWL") return nil, fmt.Errorf("window capture requires Hyprland or Mango")
} }
} }
@@ -285,6 +253,93 @@ func getMiracleFocusedMonitor() string {
return "" return ""
} }
type mangoMonitor struct {
Name string `json:"name"`
Active bool `json:"active"`
X int32 `json:"x"`
Y int32 `json:"y"`
Scale float64 `json:"scale"`
}
func getMangoMonitors() []mangoMonitor {
output, err := exec.Command("mmsg", "get", "all-monitors").Output()
if err != nil {
return nil
}
var data struct {
Monitors []mangoMonitor `json:"monitors"`
}
if err := json.Unmarshal(output, &data); err != nil {
return nil
}
return data.Monitors
}
func getMangoFocusedMonitor() string {
for _, m := range getMangoMonitors() {
if m.Active {
return m.Name
}
}
return ""
}
type mangoClient struct {
Monitor string `json:"monitor"`
IsFocused bool `json:"is_focused"`
X int32 `json:"x"`
Y int32 `json:"y"`
Width int32 `json:"width"`
Height int32 `json:"height"`
}
func getMangoActiveWindow() (*WindowGeometry, error) {
output, err := exec.Command("mmsg", "get", "all-clients").Output()
if err != nil {
return nil, fmt.Errorf("mmsg get all-clients: %w", err)
}
var data struct {
Clients []mangoClient `json:"clients"`
}
if err := json.Unmarshal(output, &data); err != nil {
return nil, fmt.Errorf("parse all-clients: %w", err)
}
for _, c := range data.Clients {
if !c.IsFocused {
continue
}
if c.Width <= 0 || c.Height <= 0 {
return nil, fmt.Errorf("no active window")
}
geom := &WindowGeometry{
X: c.X,
Y: c.Y,
Width: c.Width,
Height: c.Height,
Output: c.Monitor,
Scale: 1.0,
}
for _, m := range getMangoMonitors() {
if m.Name != c.Monitor {
continue
}
geom.OutputX = m.X
geom.OutputY = m.Y
if m.Scale > 0 {
geom.Scale = m.Scale
}
break
}
return geom, nil
}
return nil, fmt.Errorf("no focused window")
}
type niriWorkspace struct { type niriWorkspace struct {
Output string `json:"output"` Output string `json:"output"`
IsFocused bool `json:"is_focused"` IsFocused bool `json:"is_focused"`
@@ -309,121 +364,6 @@ func getNiriFocusedMonitor() string {
return "" return ""
} }
var dwlActiveOutput string
func SetDWLActiveOutput(name string) {
dwlActiveOutput = name
}
func getDWLFocusedMonitor() string {
if dwlActiveOutput != "" {
return dwlActiveOutput
}
return queryDWLActiveOutput()
}
func queryDWLActiveOutput() string {
display, err := client.Connect("")
if err != nil {
return ""
}
ctx := display.Context()
defer ctx.Close()
registry, err := display.GetRegistry()
if err != nil {
return ""
}
var dwlManager *dwl_ipc.ZdwlIpcManagerV2
outputs := make(map[uint32]*client.Output)
registry.SetGlobalHandler(func(e client.RegistryGlobalEvent) {
switch e.Interface {
case dwl_ipc.ZdwlIpcManagerV2InterfaceName:
mgr := dwl_ipc.NewZdwlIpcManagerV2(ctx)
if err := registry.Bind(e.Name, e.Interface, e.Version, mgr); err == nil {
dwlManager = mgr
}
case client.OutputInterfaceName:
out := client.NewOutput(ctx)
version := e.Version
if version > 4 {
version = 4
}
if err := registry.Bind(e.Name, e.Interface, version, out); err == nil {
outputs[e.Name] = out
}
}
})
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
return ""
}
if dwlManager == nil || len(outputs) == 0 {
return ""
}
outputNames := make(map[uint32]string)
for name, out := range outputs {
n := name
out.SetNameHandler(func(e client.OutputNameEvent) {
outputNames[n] = e.Name
})
}
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
return ""
}
type outputState struct {
name string
active bool
gotFrame bool
}
states := make(map[uint32]*outputState)
for name, out := range outputs {
dwlOut, err := dwlManager.GetOutput(out)
if err != nil {
continue
}
state := &outputState{name: outputNames[name]}
states[name] = state
dwlOut.SetActiveHandler(func(e dwl_ipc.ZdwlIpcOutputV2ActiveEvent) {
state.active = e.Active != 0
})
dwlOut.SetFrameHandler(func(e dwl_ipc.ZdwlIpcOutputV2FrameEvent) {
state.gotFrame = true
})
}
allFramesReceived := func() bool {
for _, s := range states {
if !s.gotFrame {
return false
}
}
return true
}
for !allFramesReceived() {
if err := ctx.Dispatch(); err != nil {
return ""
}
}
for _, state := range states {
if state.active {
return state.name
}
}
return ""
}
func GetFocusedMonitor() string { func GetFocusedMonitor() string {
switch DetectCompositor() { switch DetectCompositor() {
case CompositorHyprland: case CompositorHyprland:
@@ -436,8 +376,8 @@ func GetFocusedMonitor() string {
return getMiracleFocusedMonitor() return getMiracleFocusedMonitor()
case CompositorNiri: case CompositorNiri:
return getNiriFocusedMonitor() return getNiriFocusedMonitor()
case CompositorDWL: case CompositorMango:
return getDWLFocusedMonitor() return getMangoFocusedMonitor()
} }
return "" return ""
} }
@@ -534,161 +474,3 @@ func getAllOutputInfos() map[string]*outputInfo {
} }
return result return result
} }
func getOutputInfo(outputName string) (*outputInfo, bool) {
infos := getAllOutputInfos()
if infos == nil {
return nil, false
}
info, ok := infos[outputName]
return info, ok
}
func getDWLActiveWindow() (*WindowGeometry, error) {
display, err := client.Connect("")
if err != nil {
return nil, fmt.Errorf("connect: %w", err)
}
ctx := display.Context()
defer ctx.Close()
registry, err := display.GetRegistry()
if err != nil {
return nil, fmt.Errorf("get registry: %w", err)
}
var dwlManager *dwl_ipc.ZdwlIpcManagerV2
outputs := make(map[uint32]*client.Output)
registry.SetGlobalHandler(func(e client.RegistryGlobalEvent) {
switch e.Interface {
case dwl_ipc.ZdwlIpcManagerV2InterfaceName:
mgr := dwl_ipc.NewZdwlIpcManagerV2(ctx)
if err := registry.Bind(e.Name, e.Interface, e.Version, mgr); err == nil {
dwlManager = mgr
}
case client.OutputInterfaceName:
out := client.NewOutput(ctx)
version := e.Version
if version > 4 {
version = 4
}
if err := registry.Bind(e.Name, e.Interface, version, out); err == nil {
outputs[e.Name] = out
}
}
})
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
return nil, fmt.Errorf("roundtrip: %w", err)
}
if dwlManager == nil {
return nil, fmt.Errorf("dwl_ipc_manager not available")
}
if len(outputs) == 0 {
return nil, fmt.Errorf("no outputs found")
}
outputNames := make(map[uint32]string)
for name, out := range outputs {
n := name
out.SetNameHandler(func(e client.OutputNameEvent) {
outputNames[n] = e.Name
})
}
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
return nil, fmt.Errorf("roundtrip: %w", err)
}
type dwlOutputState struct {
output *dwl_ipc.ZdwlIpcOutputV2
name string
active bool
x, y int32
w, h int32
scalefactor uint32
gotFrame bool
}
dwlOutputs := make(map[uint32]*dwlOutputState)
for name, out := range outputs {
dwlOut, err := dwlManager.GetOutput(out)
if err != nil {
continue
}
state := &dwlOutputState{output: dwlOut, name: outputNames[name]}
dwlOutputs[name] = state
dwlOut.SetActiveHandler(func(e dwl_ipc.ZdwlIpcOutputV2ActiveEvent) {
state.active = e.Active != 0
})
dwlOut.SetXHandler(func(e dwl_ipc.ZdwlIpcOutputV2XEvent) {
state.x = e.X
})
dwlOut.SetYHandler(func(e dwl_ipc.ZdwlIpcOutputV2YEvent) {
state.y = e.Y
})
dwlOut.SetWidthHandler(func(e dwl_ipc.ZdwlIpcOutputV2WidthEvent) {
state.w = e.Width
})
dwlOut.SetHeightHandler(func(e dwl_ipc.ZdwlIpcOutputV2HeightEvent) {
state.h = e.Height
})
dwlOut.SetScalefactorHandler(func(e dwl_ipc.ZdwlIpcOutputV2ScalefactorEvent) {
state.scalefactor = e.Scalefactor
})
dwlOut.SetFrameHandler(func(e dwl_ipc.ZdwlIpcOutputV2FrameEvent) {
state.gotFrame = true
})
}
allFramesReceived := func() bool {
for _, s := range dwlOutputs {
if !s.gotFrame {
return false
}
}
return true
}
for !allFramesReceived() {
if err := ctx.Dispatch(); err != nil {
return nil, fmt.Errorf("dispatch: %w", err)
}
}
for _, state := range dwlOutputs {
if !state.active {
continue
}
if state.w <= 0 || state.h <= 0 {
return nil, fmt.Errorf("no active window")
}
scale := float64(state.scalefactor) / 100.0
if scale <= 0 {
scale = 1.0
}
geom := &WindowGeometry{
X: state.x,
Y: state.y,
Width: state.w,
Height: state.h,
Output: state.name,
Scale: scale,
}
if info, ok := getOutputInfo(state.name); ok {
geom.OutputX = info.x
geom.OutputY = info.y
geom.OutputTransform = info.transform
}
return geom, nil
}
return nil, fmt.Errorf("no active output found")
}
+4 -4
View File
@@ -156,14 +156,14 @@ func (s *Screenshoter) captureWindow() (*CaptureResult, error) {
switch DetectCompositor() { switch DetectCompositor() {
case CompositorHyprland: case CompositorHyprland:
return s.captureAndCrop(output, region) return s.captureAndCrop(output, region)
case CompositorDWL: case CompositorMango:
return s.captureDWLWindow(output, region, geom) return s.captureMangoWindow(output, region, geom)
default: default:
return s.captureRegionOnOutput(output, region) return s.captureRegionOnOutput(output, region)
} }
} }
func (s *Screenshoter) captureDWLWindow(output *WaylandOutput, region Region, geom *WindowGeometry) (*CaptureResult, error) { func (s *Screenshoter) captureMangoWindow(output *WaylandOutput, region Region, geom *WindowGeometry) (*CaptureResult, error) {
result, err := s.captureWholeOutput(output) result, err := s.captureWholeOutput(output)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -628,7 +628,7 @@ func (s *Screenshoter) captureRegionOnOutput(output *WaylandOutput, region Regio
w := int32(float64(region.Width) * scale) w := int32(float64(region.Width) * scale)
h := int32(float64(region.Height) * scale) h := int32(float64(region.Height) * scale)
if DetectCompositor() == CompositorDWL { if DetectCompositor() == CompositorMango {
scaledOutW := int32(float64(output.width) * scale) scaledOutW := int32(float64(output.width) * scale)
scaledOutH := int32(float64(output.height) * scale) scaledOutH := int32(float64(output.height) * scale)
if localX >= scaledOutW { if localX >= scaledOutW {
+32 -31
View File
@@ -935,7 +935,7 @@ func (m *Manager) CreateHistoryEntryFromPinned(pinnedEntry *Entry) error {
Pinned: false, Pinned: false,
} }
if err := m.storeEntryWithoutDedup(newEntry); err != nil { if err := m.storeEntry(newEntry); err != nil {
return err return err
} }
@@ -945,36 +945,6 @@ func (m *Manager) CreateHistoryEntryFromPinned(pinnedEntry *Entry) error {
return nil return nil
} }
func (m *Manager) storeEntryWithoutDedup(entry Entry) error {
if m.db == nil {
return fmt.Errorf("database not available")
}
entry.Hash = computeHash(entry.Data)
return m.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
id, err := b.NextSequence()
if err != nil {
return err
}
entry.ID = id
encoded, err := encodeEntry(entry)
if err != nil {
return err
}
if err := b.Put(itob(id), encoded); err != nil {
return err
}
return m.trimLengthInTx(b)
})
}
func (m *Manager) ClearHistory() { func (m *Manager) ClearHistory() {
if m.db == nil { if m.db == nil {
return return
@@ -1653,6 +1623,37 @@ func (m *Manager) UnpinEntry(id uint64) error {
return err return err
} }
if entry.Pinned {
currentKey := itob(id)
var keepKey []byte
var deleteKeys [][]byte
c := b.Cursor()
for k, v := c.Last(); k != nil; k, v = c.Prev() {
if bytes.Equal(k, currentKey) || extractHash(v) != entry.Hash {
continue
}
duplicate, err := decodeEntryMeta(v)
if err == nil && !duplicate.Pinned {
key := append([]byte(nil), k...)
if keepKey == nil {
keepKey = key
} else {
deleteKeys = append(deleteKeys, key)
}
}
}
if keepKey != nil {
for _, key := range deleteKeys {
if err := b.Delete(key); err != nil {
return err
}
}
return b.Delete(currentKey)
}
}
entry.Pinned = false entry.Pinned = false
encoded, err := encodeEntry(entry) encoded, err := encodeEntry(entry)
if err != nil { if err != nil {
@@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
bolt "go.etcd.io/bbolt"
mocks_wlcontext "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlcontext" mocks_wlcontext "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlcontext"
) )
@@ -273,6 +274,110 @@ func TestHandleGetEntry_MissingIDReturnsNullResult(t *testing.T) {
assert.Nil(t, resp.Result) assert.Nil(t, resp.Result)
} }
func TestUnpinEntry_KeepsTopUnpinnedDuplicate(t *testing.T) {
m := newTestManagerWithDB(t)
require.NoError(t, m.storeEntry(Entry{
Data: []byte("saved content"),
MimeType: "text/plain;charset=utf-8",
Preview: "saved content",
Size: len("saved content"),
Timestamp: time.Now().Add(-time.Minute).Truncate(time.Second),
IsImage: false,
}))
history := m.GetHistory()
require.Len(t, history, 1)
pinnedID := history[0].ID
require.NoError(t, m.PinEntry(pinnedID))
pinnedEntry, err := m.GetEntry(pinnedID)
require.NoError(t, err)
require.True(t, pinnedEntry.Pinned)
// Bypass storeEntry to simulate legacy duplicate ordinary history entries.
insertLegacyUnpinnedDuplicate := func(timestamp time.Time) Entry {
duplicate := Entry{
Data: pinnedEntry.Data,
MimeType: pinnedEntry.MimeType,
Preview: pinnedEntry.Preview,
Size: pinnedEntry.Size,
Timestamp: timestamp,
IsImage: pinnedEntry.IsImage,
Pinned: false,
}
duplicate.Hash = computeHash(duplicate.Data)
require.NoError(t, m.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
id, err := b.NextSequence()
if err != nil {
return err
}
duplicate.ID = id
encoded, err := encodeEntry(duplicate)
if err != nil {
return err
}
return b.Put(itob(id), encoded)
}))
return duplicate
}
olderHistoryDuplicate := insertLegacyUnpinnedDuplicate(time.Now().Add(time.Hour))
topHistoryDuplicate := insertLegacyUnpinnedDuplicate(time.Now().Add(-time.Hour))
require.Greater(t, topHistoryDuplicate.ID, olderHistoryDuplicate.ID)
require.True(t, olderHistoryDuplicate.Timestamp.After(topHistoryDuplicate.Timestamp))
history = m.GetHistory()
require.Len(t, history, 3)
require.Equal(t, topHistoryDuplicate.ID, history[0].ID)
require.NoError(t, m.UnpinEntry(pinnedID))
history = m.GetHistory()
require.Len(t, history, 1)
assert.False(t, history[0].Pinned)
assert.Equal(t, pinnedEntry.Hash, history[0].Hash)
assert.Equal(t, topHistoryDuplicate.ID, history[0].ID)
}
func TestCreateHistoryEntryFromPinned_KeepsLatestUnpinnedDuplicate(t *testing.T) {
m := newTestManagerWithDB(t)
require.NoError(t, m.storeEntry(Entry{
Data: []byte("saved content"),
MimeType: "text/plain;charset=utf-8",
Preview: "saved content",
Size: len("saved content"),
Timestamp: time.Now().Add(-time.Minute).Truncate(time.Second),
IsImage: false,
}))
history := m.GetHistory()
require.Len(t, history, 1)
pinnedID := history[0].ID
require.NoError(t, m.PinEntry(pinnedID))
pinnedEntry, err := m.GetEntry(pinnedID)
require.NoError(t, err)
require.True(t, pinnedEntry.Pinned)
require.NoError(t, m.CreateHistoryEntryFromPinned(pinnedEntry))
firstDuplicate := m.GetHistory()[0]
require.NotEqual(t, pinnedID, firstDuplicate.ID)
require.NoError(t, m.CreateHistoryEntryFromPinned(pinnedEntry))
latestDuplicate := m.GetHistory()[0]
history = m.GetHistory()
require.Len(t, history, 2)
assert.Equal(t, latestDuplicate.ID, history[0].ID)
assert.False(t, history[0].Pinned)
assert.Equal(t, pinnedID, history[1].ID)
assert.True(t, history[1].Pinned)
assert.NotEqual(t, firstDuplicate.ID, latestDuplicate.ID)
}
func TestManager_ConcurrentSubscriberAccess(t *testing.T) { func TestManager_ConcurrentSubscriberAccess(t *testing.T) {
m := &Manager{ m := &Manager{
subscribers: make(map[string]chan State), subscribers: make(map[string]chan State),
-138
View File
@@ -1,138 +0,0 @@
package dwl
import (
"encoding/json"
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
)
type SuccessResult struct {
Success bool `json:"success"`
Message string `json:"message"`
}
func HandleRequest(conn net.Conn, req models.Request, manager *Manager) {
if manager == nil {
models.RespondError(conn, req.ID, "dwl manager not initialized")
return
}
switch req.Method {
case "dwl.getState":
handleGetState(conn, req, manager)
case "dwl.setTags":
handleSetTags(conn, req, manager)
case "dwl.setClientTags":
handleSetClientTags(conn, req, manager)
case "dwl.setLayout":
handleSetLayout(conn, req, manager)
case "dwl.subscribe":
handleSubscribe(conn, req, manager)
default:
models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method))
}
}
func handleGetState(conn net.Conn, req models.Request, manager *Manager) {
state := manager.GetState()
models.Respond(conn, req.ID, state)
}
func handleSetTags(conn net.Conn, req models.Request, manager *Manager) {
output, ok := models.Get[string](req, "output")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'output' parameter")
return
}
tagmask, ok := models.Get[float64](req, "tagmask")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'tagmask' parameter")
return
}
toggleTagset, ok := models.Get[float64](req, "toggleTagset")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'toggleTagset' parameter")
return
}
if err := manager.SetTags(output, uint32(tagmask), uint32(toggleTagset)); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, SuccessResult{Success: true, Message: "tags set"})
}
func handleSetClientTags(conn net.Conn, req models.Request, manager *Manager) {
output, ok := models.Get[string](req, "output")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'output' parameter")
return
}
andTags, ok := models.Get[float64](req, "andTags")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'andTags' parameter")
return
}
xorTags, ok := models.Get[float64](req, "xorTags")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'xorTags' parameter")
return
}
if err := manager.SetClientTags(output, uint32(andTags), uint32(xorTags)); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, SuccessResult{Success: true, Message: "client tags set"})
}
func handleSetLayout(conn net.Conn, req models.Request, manager *Manager) {
output, ok := models.Get[string](req, "output")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'output' parameter")
return
}
index, ok := models.Get[float64](req, "index")
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'index' parameter")
return
}
if err := manager.SetLayout(output, uint32(index)); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, SuccessResult{Success: true, Message: "layout set"})
}
func handleSubscribe(conn net.Conn, req models.Request, manager *Manager) {
clientID := fmt.Sprintf("client-%p", conn)
stateChan := manager.Subscribe(clientID)
defer manager.Unsubscribe(clientID)
initialState := manager.GetState()
if err := json.NewEncoder(conn).Encode(models.Response[State]{
ID: req.ID,
Result: &initialState,
}); err != nil {
return
}
for state := range stateChan {
if err := json.NewEncoder(conn).Encode(models.Response[State]{
Result: &state,
}); err != nil {
return
}
}
}
-522
View File
@@ -1,522 +0,0 @@
package dwl
import (
"fmt"
"time"
wlclient "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
"github.com/AvengeMedia/DankMaterialShell/core/internal/proto/dwl_ipc"
)
func NewManager(display wlclient.WaylandDisplay) (*Manager, error) {
m := &Manager{
display: display,
ctx: display.Context(),
cmdq: make(chan cmd, 128),
outputSetupReq: make(chan uint32, 16),
stopChan: make(chan struct{}),
dirty: make(chan struct{}, 1),
layouts: make([]string, 0),
}
if err := m.setupRegistry(); err != nil {
return nil, err
}
m.updateState()
m.notifierWg.Add(1)
go m.notifier()
m.wg.Add(1)
go m.waylandActor()
return m, nil
}
func (m *Manager) post(fn func()) {
select {
case m.cmdq <- cmd{fn: fn}:
default:
log.Warn("DWL actor command queue full, dropping command")
}
}
func (m *Manager) waylandActor() {
defer m.wg.Done()
for {
select {
case <-m.stopChan:
return
case c := <-m.cmdq:
c.fn()
case outputID := <-m.outputSetupReq:
out, exists := m.outputs.Load(outputID)
if !exists {
log.Warnf("DWL: Output %d no longer exists, skipping setup", outputID)
continue
}
if out.ipcOutput != nil {
continue
}
mgr, ok := m.manager.(*dwl_ipc.ZdwlIpcManagerV2)
if !ok || mgr == nil {
log.Errorf("DWL: Manager not available for output %d setup", outputID)
continue
}
log.Infof("DWL: Setting up ipcOutput for dynamically added output %d", outputID)
if err := m.setupOutput(mgr, out.output); err != nil {
log.Errorf("DWL: Failed to setup output %d: %v", outputID, err)
} else {
m.updateState()
}
}
}
}
func (m *Manager) setupRegistry() error {
log.Info("DWL: starting registry setup")
registry, err := m.display.GetRegistry()
if err != nil {
return fmt.Errorf("failed to get registry: %w", err)
}
m.registry = registry
outputs := make([]*wlclient.Output, 0)
outputRegNames := make(map[uint32]uint32)
var dwlMgr *dwl_ipc.ZdwlIpcManagerV2
registry.SetGlobalHandler(func(e wlclient.RegistryGlobalEvent) {
switch e.Interface {
case dwl_ipc.ZdwlIpcManagerV2InterfaceName:
log.Infof("DWL: found %s", dwl_ipc.ZdwlIpcManagerV2InterfaceName)
manager := dwl_ipc.NewZdwlIpcManagerV2(m.ctx)
version := e.Version
if version > 2 {
version = 2
}
if err := registry.Bind(e.Name, e.Interface, version, manager); err == nil {
dwlMgr = manager
log.Info("DWL: manager bound successfully")
// Set handlers immediately after binding, before roundtrips
manager.SetTagsHandler(func(e dwl_ipc.ZdwlIpcManagerV2TagsEvent) {
log.Infof("DWL: Tags count: %d", e.Amount)
m.tagCount = e.Amount
m.updateState()
})
manager.SetLayoutHandler(func(e dwl_ipc.ZdwlIpcManagerV2LayoutEvent) {
log.Infof("DWL: Layout: %s", e.Name)
m.layouts = append(m.layouts, e.Name)
m.updateState()
})
} else {
log.Errorf("DWL: failed to bind manager: %v", err)
}
case "wl_output":
log.Debugf("DWL: found wl_output (name=%d)", e.Name)
output := wlclient.NewOutput(m.ctx)
outState := &outputState{
registryName: e.Name,
output: output,
tags: make([]TagState, 0),
}
output.SetNameHandler(func(ev wlclient.OutputNameEvent) {
log.Debugf("DWL: Output name: %s (registry=%d)", ev.Name, e.Name)
outState.name = ev.Name
})
output.SetDescriptionHandler(func(ev wlclient.OutputDescriptionEvent) {
log.Debugf("DWL: Output description: %s", ev.Description)
})
version := e.Version
if version > 4 {
version = 4
}
if err := registry.Bind(e.Name, e.Interface, version, output); err == nil {
outputID := output.ID()
outState.id = outputID
log.Infof("DWL: Bound wl_output id=%d registry_name=%d", outputID, e.Name)
outputs = append(outputs, output)
outputRegNames[outputID] = e.Name
m.outputs.Store(outputID, outState)
if m.manager != nil {
select {
case m.outputSetupReq <- outputID:
log.Debugf("DWL: Queued setup for output %d", outputID)
default:
log.Warnf("DWL: Setup queue full, output %d will not be initialized", outputID)
}
}
} else {
log.Errorf("DWL: Failed to bind wl_output: %v", err)
}
}
})
registry.SetGlobalRemoveHandler(func(e wlclient.RegistryGlobalRemoveEvent) {
m.post(func() {
var outToRelease *outputState
m.outputs.Range(func(id uint32, out *outputState) bool {
if out.registryName == e.Name {
log.Infof("DWL: Output %d removed", id)
outToRelease = out
m.outputs.Delete(id)
return false
}
return true
})
if outToRelease != nil {
if ipcOut, ok := outToRelease.ipcOutput.(*dwl_ipc.ZdwlIpcOutputV2); ok && ipcOut != nil {
m.wlMutex.Lock()
ipcOut.Release()
m.wlMutex.Unlock()
log.Debugf("DWL: Released ipcOutput for removed output %d", outToRelease.id)
}
m.updateState()
}
})
})
if err := m.display.Roundtrip(); err != nil {
return fmt.Errorf("first roundtrip failed: %w", err)
}
if err := m.display.Roundtrip(); err != nil {
return fmt.Errorf("second roundtrip failed: %w", err)
}
if dwlMgr == nil {
log.Info("DWL: manager not found in registry")
return fmt.Errorf("dwl_ipc_manager_v2 not available")
}
m.manager = dwlMgr
for _, output := range outputs {
if err := m.setupOutput(dwlMgr, output); err != nil {
log.Warnf("DWL: Failed to setup output %d: %v", output.ID(), err)
}
}
if err := m.display.Roundtrip(); err != nil {
return fmt.Errorf("final roundtrip failed: %w", err)
}
log.Info("DWL: registry setup complete")
return nil
}
func (m *Manager) setupOutput(manager *dwl_ipc.ZdwlIpcManagerV2, output *wlclient.Output) error {
m.wlMutex.Lock()
ipcOutput, err := manager.GetOutput(output)
m.wlMutex.Unlock()
if err != nil {
return fmt.Errorf("failed to get dwl output: %w", err)
}
outState, exists := m.outputs.Load(output.ID())
if !exists {
return fmt.Errorf("output state not found for id %d", output.ID())
}
outState.ipcOutput = ipcOutput
ipcOutput.SetActiveHandler(func(e dwl_ipc.ZdwlIpcOutputV2ActiveEvent) {
outState.active = e.Active
})
ipcOutput.SetTagHandler(func(e dwl_ipc.ZdwlIpcOutputV2TagEvent) {
updated := false
for i, tag := range outState.tags {
if tag.Tag == e.Tag {
outState.tags[i] = TagState{
Tag: e.Tag,
State: e.State,
Clients: e.Clients,
Focused: e.Focused,
}
updated = true
break
}
}
if !updated {
outState.tags = append(outState.tags, TagState{
Tag: e.Tag,
State: e.State,
Clients: e.Clients,
Focused: e.Focused,
})
}
m.updateState()
})
ipcOutput.SetLayoutHandler(func(e dwl_ipc.ZdwlIpcOutputV2LayoutEvent) {
outState.layout = e.Layout
})
ipcOutput.SetTitleHandler(func(e dwl_ipc.ZdwlIpcOutputV2TitleEvent) {
outState.title = e.Title
})
ipcOutput.SetAppidHandler(func(e dwl_ipc.ZdwlIpcOutputV2AppidEvent) {
outState.appID = e.Appid
})
ipcOutput.SetLayoutSymbolHandler(func(e dwl_ipc.ZdwlIpcOutputV2LayoutSymbolEvent) {
outState.layoutSymbol = e.Layout
})
ipcOutput.SetKbLayoutHandler(func(e dwl_ipc.ZdwlIpcOutputV2KbLayoutEvent) {
outState.kbLayout = e.KbLayout
})
ipcOutput.SetKeymodeHandler(func(e dwl_ipc.ZdwlIpcOutputV2KeymodeEvent) {
outState.keymode = e.Keymode
})
ipcOutput.SetFrameHandler(func(e dwl_ipc.ZdwlIpcOutputV2FrameEvent) {
m.updateState()
})
return nil
}
func (m *Manager) updateState() {
outputs := make(map[string]*OutputState)
activeOutput := ""
m.outputs.Range(func(key uint32, out *outputState) bool {
name := out.name
if name == "" {
name = fmt.Sprintf("output-%d", out.id)
}
tagsCopy := make([]TagState, len(out.tags))
copy(tagsCopy, out.tags)
outputs[name] = &OutputState{
Name: name,
Active: out.active,
Tags: tagsCopy,
Layout: out.layout,
LayoutSymbol: out.layoutSymbol,
Title: out.title,
AppID: out.appID,
KbLayout: out.kbLayout,
Keymode: out.keymode,
}
if out.active != 0 {
activeOutput = name
}
return true
})
newState := State{
Outputs: outputs,
TagCount: m.tagCount,
Layouts: m.layouts,
ActiveOutput: activeOutput,
}
m.stateMutex.Lock()
m.state = &newState
m.stateMutex.Unlock()
m.notifySubscribers()
}
func (m *Manager) notifier() {
defer m.notifierWg.Done()
const minGap = 100 * time.Millisecond
timer := time.NewTimer(minGap)
timer.Stop()
var pending bool
for {
select {
case <-m.stopChan:
timer.Stop()
return
case <-m.dirty:
if pending {
continue
}
pending = true
timer.Reset(minGap)
case <-timer.C:
if !pending {
continue
}
currentState := m.GetState()
if m.lastNotified != nil && !stateChanged(m.lastNotified, &currentState) {
pending = false
continue
}
m.subscribers.Range(func(key string, ch chan State) bool {
select {
case ch <- currentState:
default:
log.Warn("DWL: subscriber channel full, dropping update")
}
return true
})
stateCopy := currentState
m.lastNotified = &stateCopy
pending = false
}
}
}
func (m *Manager) ensureOutputSetup(out *outputState) error {
if out.ipcOutput != nil {
return nil
}
return fmt.Errorf("output not yet initialized - setup in progress, retry in a moment")
}
func (m *Manager) SetTags(outputName string, tagmask uint32, toggleTagset uint32) error {
availableOutputs := make([]string, 0)
var targetOut *outputState
m.outputs.Range(func(key uint32, out *outputState) bool {
name := out.name
if name == "" {
name = fmt.Sprintf("output-%d", out.id)
}
availableOutputs = append(availableOutputs, name)
if name == outputName {
targetOut = out
return false
}
return true
})
if targetOut == nil {
return fmt.Errorf("output not found: %s (available: %v)", outputName, availableOutputs)
}
if err := m.ensureOutputSetup(targetOut); err != nil {
return fmt.Errorf("failed to setup output %s: %w", outputName, err)
}
ipcOut, ok := targetOut.ipcOutput.(*dwl_ipc.ZdwlIpcOutputV2)
if !ok {
return fmt.Errorf("output %s has invalid ipcOutput type", outputName)
}
m.wlMutex.Lock()
err := ipcOut.SetTags(tagmask, toggleTagset)
m.wlMutex.Unlock()
return err
}
func (m *Manager) SetClientTags(outputName string, andTags uint32, xorTags uint32) error {
var targetOut *outputState
m.outputs.Range(func(key uint32, out *outputState) bool {
name := out.name
if name == "" {
name = fmt.Sprintf("output-%d", out.id)
}
if name == outputName {
targetOut = out
return false
}
return true
})
if targetOut == nil {
return fmt.Errorf("output not found: %s", outputName)
}
if err := m.ensureOutputSetup(targetOut); err != nil {
return fmt.Errorf("failed to setup output %s: %w", outputName, err)
}
ipcOut, ok := targetOut.ipcOutput.(*dwl_ipc.ZdwlIpcOutputV2)
if !ok {
return fmt.Errorf("output %s has invalid ipcOutput type", outputName)
}
m.wlMutex.Lock()
err := ipcOut.SetClientTags(andTags, xorTags)
m.wlMutex.Unlock()
return err
}
func (m *Manager) SetLayout(outputName string, index uint32) error {
var targetOut *outputState
m.outputs.Range(func(key uint32, out *outputState) bool {
name := out.name
if name == "" {
name = fmt.Sprintf("output-%d", out.id)
}
if name == outputName {
targetOut = out
return false
}
return true
})
if targetOut == nil {
return fmt.Errorf("output not found: %s", outputName)
}
if err := m.ensureOutputSetup(targetOut); err != nil {
return fmt.Errorf("failed to setup output %s: %w", outputName, err)
}
ipcOut, ok := targetOut.ipcOutput.(*dwl_ipc.ZdwlIpcOutputV2)
if !ok {
return fmt.Errorf("output %s has invalid ipcOutput type", outputName)
}
m.wlMutex.Lock()
err := ipcOut.SetLayout(index)
m.wlMutex.Unlock()
return err
}
func (m *Manager) Close() {
close(m.stopChan)
m.wg.Wait()
m.notifierWg.Wait()
m.subscribers.Range(func(key string, ch chan State) bool {
close(ch)
m.subscribers.Delete(key)
return true
})
m.outputs.Range(func(key uint32, out *outputState) bool {
if ipcOut, ok := out.ipcOutput.(*dwl_ipc.ZdwlIpcOutputV2); ok {
ipcOut.Release()
}
m.outputs.Delete(key)
return true
})
if mgr, ok := m.manager.(*dwl_ipc.ZdwlIpcManagerV2); ok {
mgr.Release()
}
}
-366
View File
@@ -1,366 +0,0 @@
package dwl
import (
"errors"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
mocks_wlclient "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlclient"
)
func TestStateChanged_BothNil(t *testing.T) {
assert.True(t, stateChanged(nil, nil))
}
func TestStateChanged_OneNil(t *testing.T) {
s := &State{TagCount: 9}
assert.True(t, stateChanged(s, nil))
assert.True(t, stateChanged(nil, s))
}
func TestStateChanged_TagCountDiffers(t *testing.T) {
a := &State{TagCount: 9, Outputs: make(map[string]*OutputState), Layouts: []string{}}
b := &State{TagCount: 10, Outputs: make(map[string]*OutputState), Layouts: []string{}}
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_LayoutLengthDiffers(t *testing.T) {
a := &State{TagCount: 9, Layouts: []string{"tile"}, Outputs: make(map[string]*OutputState)}
b := &State{TagCount: 9, Layouts: []string{"tile", "monocle"}, Outputs: make(map[string]*OutputState)}
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_ActiveOutputDiffers(t *testing.T) {
a := &State{TagCount: 9, ActiveOutput: "eDP-1", Outputs: make(map[string]*OutputState), Layouts: []string{}}
b := &State{TagCount: 9, ActiveOutput: "HDMI-A-1", Outputs: make(map[string]*OutputState), Layouts: []string{}}
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_OutputCountDiffers(t *testing.T) {
a := &State{
TagCount: 9,
Outputs: map[string]*OutputState{"eDP-1": {}},
Layouts: []string{},
}
b := &State{
TagCount: 9,
Outputs: map[string]*OutputState{},
Layouts: []string{},
}
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_OutputFieldsDiffer(t *testing.T) {
a := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Active: 1, Layout: 0, Title: "Firefox"},
},
}
b := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Active: 0, Layout: 0, Title: "Firefox"},
},
}
assert.True(t, stateChanged(a, b))
b.Outputs["eDP-1"].Active = 1
b.Outputs["eDP-1"].Layout = 1
assert.True(t, stateChanged(a, b))
b.Outputs["eDP-1"].Layout = 0
b.Outputs["eDP-1"].Title = "Code"
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_TagsDiffer(t *testing.T) {
a := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Tags: []TagState{{Tag: 1, State: 1, Clients: 2, Focused: 1}}},
},
}
b := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Tags: []TagState{{Tag: 1, State: 2, Clients: 2, Focused: 1}}},
},
}
assert.True(t, stateChanged(a, b))
b.Outputs["eDP-1"].Tags[0].State = 1
b.Outputs["eDP-1"].Tags[0].Clients = 3
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_Equal(t *testing.T) {
a := &State{
TagCount: 9,
ActiveOutput: "eDP-1",
Layouts: []string{"tile", "monocle"},
Outputs: map[string]*OutputState{
"eDP-1": {
Name: "eDP-1",
Active: 1,
Layout: 0,
LayoutSymbol: "[]=",
Title: "Firefox",
AppID: "firefox",
KbLayout: "us",
Keymode: "",
Tags: []TagState{{Tag: 1, State: 1, Clients: 2, Focused: 1}},
},
},
}
b := &State{
TagCount: 9,
ActiveOutput: "eDP-1",
Layouts: []string{"tile", "monocle"},
Outputs: map[string]*OutputState{
"eDP-1": {
Name: "eDP-1",
Active: 1,
Layout: 0,
LayoutSymbol: "[]=",
Title: "Firefox",
AppID: "firefox",
KbLayout: "us",
Keymode: "",
Tags: []TagState{{Tag: 1, State: 1, Clients: 2, Focused: 1}},
},
},
}
assert.False(t, stateChanged(a, b))
}
func TestManager_ConcurrentGetState(t *testing.T) {
m := &Manager{
state: &State{
TagCount: 9,
Layouts: []string{"tile"},
Outputs: map[string]*OutputState{"eDP-1": {Name: "eDP-1"}},
},
}
var wg sync.WaitGroup
const goroutines = 50
const iterations = 100
for i := 0; i < goroutines/2; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < iterations; j++ {
s := m.GetState()
_ = s.TagCount
_ = s.Outputs
}
}()
}
for i := 0; i < goroutines/2; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
for j := 0; j < iterations; j++ {
m.stateMutex.Lock()
m.state = &State{
TagCount: uint32(j % 10),
Layouts: []string{"tile", "monocle"},
Outputs: map[string]*OutputState{"eDP-1": {Active: uint32(j % 2)}},
}
m.stateMutex.Unlock()
}
}(i)
}
wg.Wait()
}
func TestManager_ConcurrentSubscriberAccess(t *testing.T) {
m := &Manager{
stopChan: make(chan struct{}),
dirty: make(chan struct{}, 1),
}
var wg sync.WaitGroup
const goroutines = 20
for i := 0; i < goroutines; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
subID := string(rune('a' + id))
ch := m.Subscribe(subID)
assert.NotNil(t, ch)
time.Sleep(time.Millisecond)
m.Unsubscribe(subID)
}(i)
}
wg.Wait()
}
func TestManager_SyncmapOutputsConcurrentAccess(t *testing.T) {
m := &Manager{}
var wg sync.WaitGroup
const goroutines = 30
const iterations = 50
for i := 0; i < goroutines; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := uint32(id)
for j := 0; j < iterations; j++ {
state := &outputState{
id: key,
name: "test-output",
active: uint32(j % 2),
tags: []TagState{{Tag: uint32(j), State: 1}},
}
m.outputs.Store(key, state)
if loaded, ok := m.outputs.Load(key); ok {
assert.Equal(t, key, loaded.id)
}
m.outputs.Range(func(k uint32, v *outputState) bool {
_ = v.name
_ = v.active
return true
})
}
m.outputs.Delete(key)
}(i)
}
wg.Wait()
}
func TestManager_NotifySubscribersNonBlocking(t *testing.T) {
m := &Manager{
dirty: make(chan struct{}, 1),
}
for i := 0; i < 10; i++ {
m.notifySubscribers()
}
assert.Len(t, m.dirty, 1)
}
func TestManager_PostQueueFull(t *testing.T) {
m := &Manager{
cmdq: make(chan cmd, 2),
stopChan: make(chan struct{}),
}
m.post(func() {})
m.post(func() {})
m.post(func() {})
m.post(func() {})
assert.Len(t, m.cmdq, 2)
}
func TestManager_GetStateNilState(t *testing.T) {
m := &Manager{}
s := m.GetState()
assert.NotNil(t, s.Outputs)
assert.NotNil(t, s.Layouts)
assert.Equal(t, uint32(0), s.TagCount)
}
func TestTagState_Fields(t *testing.T) {
tag := TagState{
Tag: 1,
State: 2,
Clients: 3,
Focused: 1,
}
assert.Equal(t, uint32(1), tag.Tag)
assert.Equal(t, uint32(2), tag.State)
assert.Equal(t, uint32(3), tag.Clients)
assert.Equal(t, uint32(1), tag.Focused)
}
func TestOutputState_Fields(t *testing.T) {
out := OutputState{
Name: "eDP-1",
Active: 1,
Tags: []TagState{{Tag: 1}},
Layout: 0,
LayoutSymbol: "[]=",
Title: "Firefox",
AppID: "firefox",
KbLayout: "us",
Keymode: "",
}
assert.Equal(t, "eDP-1", out.Name)
assert.Equal(t, uint32(1), out.Active)
assert.Len(t, out.Tags, 1)
assert.Equal(t, "[]=", out.LayoutSymbol)
}
func TestStateChanged_NewOutputAppears(t *testing.T) {
a := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Name: "eDP-1"},
},
}
b := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Name: "eDP-1"},
"HDMI-A-1": {Name: "HDMI-A-1"},
},
}
assert.True(t, stateChanged(a, b))
}
func TestStateChanged_TagsLengthDiffers(t *testing.T) {
a := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Tags: []TagState{{Tag: 1}}},
},
}
b := &State{
TagCount: 9,
Layouts: []string{},
Outputs: map[string]*OutputState{
"eDP-1": {Tags: []TagState{{Tag: 1}, {Tag: 2}}},
},
}
assert.True(t, stateChanged(a, b))
}
func TestNewManager_GetRegistryError(t *testing.T) {
mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t)
mockDisplay.EXPECT().Context().Return(nil)
mockDisplay.EXPECT().GetRegistry().Return(nil, errors.New("failed to get registry"))
_, err := NewManager(mockDisplay)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to get registry")
}
-176
View File
@@ -1,176 +0,0 @@
package dwl
import (
"sync"
wlclient "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/syncmap"
)
type TagState struct {
Tag uint32 `json:"tag"`
State uint32 `json:"state"`
Clients uint32 `json:"clients"`
Focused uint32 `json:"focused"`
}
type OutputState struct {
Name string `json:"name"`
Active uint32 `json:"active"`
Tags []TagState `json:"tags"`
Layout uint32 `json:"layout"`
LayoutSymbol string `json:"layoutSymbol"`
Title string `json:"title"`
AppID string `json:"appId"`
KbLayout string `json:"kbLayout"`
Keymode string `json:"keymode"`
}
type State struct {
Outputs map[string]*OutputState `json:"outputs"`
TagCount uint32 `json:"tagCount"`
Layouts []string `json:"layouts"`
ActiveOutput string `json:"activeOutput"`
}
type cmd struct {
fn func()
}
type Manager struct {
display wlclient.WaylandDisplay
ctx *wlclient.Context
registry *wlclient.Registry
manager any
outputs syncmap.Map[uint32, *outputState]
tagCount uint32
layouts []string
wlMutex sync.Mutex
cmdq chan cmd
outputSetupReq chan uint32
stopChan chan struct{}
wg sync.WaitGroup
subscribers syncmap.Map[string, chan State]
dirty chan struct{}
notifierWg sync.WaitGroup
lastNotified *State
stateMutex sync.RWMutex
state *State
}
type outputState struct {
id uint32
registryName uint32
output *wlclient.Output
ipcOutput any
name string
active uint32
tags []TagState
layout uint32
layoutSymbol string
title string
appID string
kbLayout string
keymode string
}
func (m *Manager) GetState() State {
m.stateMutex.RLock()
defer m.stateMutex.RUnlock()
if m.state == nil {
return State{
Outputs: make(map[string]*OutputState),
Layouts: []string{},
TagCount: 0,
}
}
stateCopy := *m.state
return stateCopy
}
func (m *Manager) Subscribe(id string) chan State {
ch := make(chan State, 64)
m.subscribers.Store(id, ch)
return ch
}
func (m *Manager) Unsubscribe(id string) {
if val, ok := m.subscribers.LoadAndDelete(id); ok {
close(val)
}
}
func (m *Manager) notifySubscribers() {
select {
case m.dirty <- struct{}{}:
default:
}
}
func stateChanged(old, new *State) bool {
if old == nil || new == nil {
return true
}
if old.TagCount != new.TagCount {
return true
}
if len(old.Layouts) != len(new.Layouts) {
return true
}
if old.ActiveOutput != new.ActiveOutput {
return true
}
if len(old.Outputs) != len(new.Outputs) {
return true
}
for name, newOut := range new.Outputs {
oldOut, exists := old.Outputs[name]
if !exists {
return true
}
if oldOut.Active != newOut.Active {
return true
}
if oldOut.Layout != newOut.Layout {
return true
}
if oldOut.LayoutSymbol != newOut.LayoutSymbol {
return true
}
if oldOut.Title != newOut.Title {
return true
}
if oldOut.AppID != newOut.AppID {
return true
}
if oldOut.KbLayout != newOut.KbLayout {
return true
}
if oldOut.Keymode != newOut.Keymode {
return true
}
if len(oldOut.Tags) != len(newOut.Tags) {
return true
}
for i, newTag := range newOut.Tags {
if i >= len(oldOut.Tags) {
return true
}
oldTag := oldOut.Tags[i]
if oldTag.Tag != newTag.Tag || oldTag.State != newTag.State ||
oldTag.Clients != newTag.Clients || oldTag.Focused != newTag.Focused {
return true
}
}
}
return false
}
+71 -1
View File
@@ -6,6 +6,7 @@ import (
"os" "os"
"sync" "sync"
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil" "github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
@@ -94,9 +95,65 @@ func (m *Manager) initializeSettings() error {
return fmt.Errorf("failed to update settings state: %w", err) return fmt.Errorf("failed to update settings state: %w", err)
} }
go m.watchSettingsChanges()
return nil return nil
} }
func (m *Manager) watchSettingsChanges() {
conn, err := dbus.ConnectSessionBus()
if err != nil {
log.Warnf("color-scheme watcher: session bus connect: %v", err)
return
}
if err := conn.AddMatchSignal(
dbus.WithMatchInterface(dbusPortalSettingsInterface),
dbus.WithMatchMember("SettingChanged"),
); err != nil {
log.Warnf("Failed to watch portal settings changes: %v", err)
conn.Close()
return
}
signals := make(chan *dbus.Signal, 64)
conn.Signal(signals)
for sig := range signals {
if sig.Name != dbusPortalSettingsInterface+".SettingChanged" {
continue
}
if len(sig.Body) < 3 {
continue
}
namespace, _ := sig.Body[0].(string)
key, _ := sig.Body[1].(string)
if namespace != "org.freedesktop.appearance" || key != "color-scheme" {
continue
}
variant, ok := sig.Body[2].(dbus.Variant)
if !ok {
continue
}
colorScheme, ok := dbusutil.As[uint32](variant)
if !ok {
continue
}
m.stateMutex.Lock()
changed := m.state.Settings.ColorScheme != colorScheme || !m.state.Settings.Available
m.state.Settings.ColorScheme = colorScheme
m.state.Settings.Available = true
m.stateMutex.Unlock()
if changed {
m.NotifySubscribers()
}
}
}
func (m *Manager) updateAccountsState() error { func (m *Manager) updateAccountsState() error {
if !m.state.Accounts.Available || m.accountsObj == nil { if !m.state.Accounts.Available || m.accountsObj == nil {
return fmt.Errorf("accounts service not available") return fmt.Errorf("accounts service not available")
@@ -134,10 +191,23 @@ func (m *Manager) updateSettingsState() error {
var variant dbus.Variant var variant dbus.Variant
err := m.settingsObj.Call(dbusPortalSettingsInterface+".ReadOne", 0, "org.freedesktop.appearance", "color-scheme").Store(&variant) err := m.settingsObj.Call(dbusPortalSettingsInterface+".ReadOne", 0, "org.freedesktop.appearance", "color-scheme").Store(&variant)
if err != nil { if err != nil {
// Older xdg-desktop-portal versions only expose the deprecated Read.
var nested dbus.Variant
if rerr := m.settingsObj.Call(dbusPortalSettingsInterface+".Read", 0, "org.freedesktop.appearance", "color-scheme").Store(&nested); rerr != nil {
log.Warnf("color-scheme: ReadOne (%v) and Read (%v) both failed", err, rerr)
return err return err
} }
variant = nested
}
if colorScheme, ok := dbusutil.As[uint32](variant); ok { colorScheme, ok := dbusutil.As[uint32](variant)
if !ok {
// Read double-wraps the value in a variant.
if inner, innerOk := variant.Value().(dbus.Variant); innerOk {
colorScheme, ok = dbusutil.As[uint32](inner)
}
}
if ok {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.Settings.ColorScheme = colorScheme m.state.Settings.ColorScheme = colorScheme
m.stateMutex.Unlock() m.stateMutex.Unlock()
+2
View File
@@ -125,6 +125,8 @@ State updates are sent whenever network configuration changes:
- `wifiConnected`: Whether associated with an access point - `wifiConnected`: Whether associated with an access point
- `wifiSSID`: Currently connected network name - `wifiSSID`: Currently connected network name
- `wifiIP`: Assigned IP address (empty until DHCP completes) - `wifiIP`: Assigned IP address (empty until DHCP completes)
- `savedWifiNetworks` (API v26+): Saved WiFi profiles exposed at SSID granularity. If a backend has multiple profiles for the same SSID, DMS merges them into one SSID-level entry. Clients talking to older servers should derive saved visible networks from `wifiNetworks` entries where `saved` is true.
- `savedWifiNetworks[].outOfRange` (API v26+): Whether the saved profile is not currently visible in scan results. Fallback entries derived from `wifiNetworks` should be treated as visible (`outOfRange: false`).
- `lastError`: Error message from last failed connection attempt - `lastError`: Error message from last failed connection attempt
### network.credentials Service Events ### network.credentials Service Events
+1
View File
@@ -67,6 +67,7 @@ type BackendState struct {
WiFiBSSID string WiFiBSSID string
WiFiSignal uint8 WiFiSignal uint8
WiFiNetworks []WiFiNetwork WiFiNetworks []WiFiNetwork
SavedWiFiNetworks []WiFiNetwork
WiFiDevices []WiFiDevice WiFiDevices []WiFiDevice
WiredConnections []WiredConnection WiredConnections []WiredConnection
VPNProfiles []VPNProfile VPNProfiles []VPNProfile
@@ -27,6 +27,19 @@ func TestHybridIwdNetworkdBackend_GetCurrentState_MergesState(t *testing.T) {
wifi.state.WiFiBSSID = "00:11:22:33:44:55" wifi.state.WiFiBSSID = "00:11:22:33:44:55"
wifi.state.WiFiSignal = 75 wifi.state.WiFiSignal = 75
wifi.state.WiFiDevice = "wlan0" wifi.state.WiFiDevice = "wlan0"
wifi.state.SavedWiFiNetworks = []WiFiNetwork{
{
SSID: "TestNetwork",
Saved: true,
Autoconnect: true,
Connected: true,
},
{
SSID: "AwayNetwork",
Saved: true,
OutOfRange: true,
},
}
l3.state.WiFiIP = "192.168.1.100" l3.state.WiFiIP = "192.168.1.100"
l3.state.EthernetConnected = false l3.state.EthernetConnected = false
@@ -42,6 +55,9 @@ func TestHybridIwdNetworkdBackend_GetCurrentState_MergesState(t *testing.T) {
assert.True(t, state.WiFiConnected) assert.True(t, state.WiFiConnected)
assert.False(t, state.EthernetConnected) assert.False(t, state.EthernetConnected)
assert.Equal(t, StatusWiFi, state.NetworkStatus) assert.Equal(t, StatusWiFi, state.NetworkStatus)
assert.Len(t, state.SavedWiFiNetworks, 2)
assert.Equal(t, "TestNetwork", state.SavedWiFiNetworks[0].SSID)
assert.True(t, state.SavedWiFiNetworks[1].OutOfRange)
} }
func TestHybridIwdNetworkdBackend_GetCurrentState_EthernetPriority(t *testing.T) { func TestHybridIwdNetworkdBackend_GetCurrentState_EthernetPriority(t *testing.T) {
@@ -80,6 +80,10 @@ func (b *IWDBackend) Initialize() error {
return fmt.Errorf("failed to discover iwd devices: %w", err) return fmt.Errorf("failed to discover iwd devices: %w", err)
} }
if err := b.updateSavedWiFiNetworks(); err != nil {
log.Warnf("Failed to get initial saved WiFi networks: %v", err)
}
if err := b.updateState(); err != nil { if err := b.updateState(); err != nil {
conn.Close() conn.Close()
return fmt.Errorf("failed to get initial state: %w", err) return fmt.Errorf("failed to get initial state: %w", err)
@@ -145,6 +149,7 @@ func (b *IWDBackend) GetCurrentState() (*BackendState, error) {
state := *b.state state := *b.state
state.WiFiNetworks = append([]WiFiNetwork(nil), b.state.WiFiNetworks...) state.WiFiNetworks = append([]WiFiNetwork(nil), b.state.WiFiNetworks...)
state.SavedWiFiNetworks = append([]WiFiNetwork(nil), b.state.SavedWiFiNetworks...)
state.WiredConnections = append([]WiredConnection(nil), b.state.WiredConnections...) state.WiredConnections = append([]WiredConnection(nil), b.state.WiredConnections...)
state.WiFiDevices = b.getWiFiDevicesLocked() state.WiFiDevices = b.getWiFiDevicesLocked()
@@ -45,12 +45,42 @@ func (b *IWDBackend) StartMonitoring(onStateChange func()) error {
} }
} }
if err := b.conn.AddMatchSignal(
dbus.WithMatchInterface(dbusPropertiesInterface),
dbus.WithMatchMember("PropertiesChanged"),
dbus.WithMatchArg(0, iwdKnownNetworkInterface),
); err != nil {
return fmt.Errorf("failed to add known network signal match: %w", err)
}
if err := b.conn.AddMatchSignal(
dbus.WithMatchInterface(dbusObjectManager),
dbus.WithMatchMember("InterfacesAdded"),
); err != nil {
return fmt.Errorf("failed to add iwd interfaces-added signal match: %w", err)
}
if err := b.conn.AddMatchSignal(
dbus.WithMatchInterface(dbusObjectManager),
dbus.WithMatchMember("InterfacesRemoved"),
); err != nil {
return fmt.Errorf("failed to add iwd interfaces-removed signal match: %w", err)
}
b.sigWG.Add(1) b.sigWG.Add(1)
go b.signalHandler(sigChan) go b.signalHandler(sigChan)
return nil return nil
} }
func (b *IWDBackend) refreshWiFiNetworkState() bool {
_, err := b.updateWiFiNetworks()
if err == nil {
return true
}
return b.updateSavedWiFiNetworks() == nil
}
func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) { func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
defer b.sigWG.Done() defer b.sigWG.Done()
@@ -66,11 +96,36 @@ func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
return return
} }
if sig.Name != dbusPropertiesInterface+".PropertiesChanged" { if sig.Name == dbusObjectManager+".InterfacesAdded" {
if len(sig.Body) >= 2 {
if interfaces, ok := sig.Body[1].(map[string]map[string]dbus.Variant); ok {
if _, ok := interfaces[iwdKnownNetworkInterface]; ok {
if b.refreshWiFiNetworkState() && b.onStateChange != nil {
b.onStateChange()
}
}
}
}
continue continue
} }
if len(sig.Body) < 2 { if sig.Name == dbusObjectManager+".InterfacesRemoved" {
if len(sig.Body) >= 2 {
if interfaces, ok := sig.Body[1].([]string); ok {
for _, iface := range interfaces {
if iface == iwdKnownNetworkInterface {
if b.refreshWiFiNetworkState() && b.onStateChange != nil {
b.onStateChange()
}
break
}
}
}
}
continue
}
if sig.Name != dbusPropertiesInterface+".PropertiesChanged" || len(sig.Body) < 2 {
continue continue
} }
@@ -87,6 +142,9 @@ func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
stateChanged := false stateChanged := false
switch iface { switch iface {
case iwdKnownNetworkInterface:
stateChanged = b.refreshWiFiNetworkState()
case iwdDeviceInterface: case iwdDeviceInterface:
if sig.Path == b.devicePath { if sig.Path == b.devicePath {
if poweredVar, ok := changed["Powered"]; ok { if poweredVar, ok := changed["Powered"]; ok {
@@ -105,13 +163,7 @@ func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
if sig.Path == b.stationPath { if sig.Path == b.stationPath {
if scanningVar, ok := changed["Scanning"]; ok { if scanningVar, ok := changed["Scanning"]; ok {
if scanning, ok := scanningVar.Value().(bool); ok && !scanning { if scanning, ok := scanningVar.Value().(bool); ok && !scanning {
networks, err := b.updateWiFiNetworks() stateChanged = b.refreshWiFiNetworkState() || stateChanged
if err == nil {
b.stateMutex.Lock()
b.state.WiFiNetworks = networks
b.stateMutex.Unlock()
stateChanged = true
}
b.stateMutex.RLock() b.stateMutex.RLock()
wifiConnected := b.state.WiFiConnected wifiConnected := b.state.WiFiConnected
@@ -236,6 +288,7 @@ func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
} }
} }
b.refreshWiFiNetworkState()
stateChanged = true stateChanged = true
if att != nil && isTarget { if att != nil && isTarget {
@@ -282,6 +335,7 @@ func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
b.state.NetworkStatus = StatusDisconnected b.state.NetworkStatus = StatusDisconnected
} }
b.stateMutex.Unlock() b.stateMutex.Unlock()
b.refreshWiFiNetworkState()
stateChanged = true stateChanged = true
} }
} }
@@ -342,6 +396,7 @@ func (b *IWDBackend) signalHandler(sigChan chan *dbus.Signal) {
stateChanged = true stateChanged = true
} }
b.stateMutex.Unlock() b.stateMutex.Unlock()
b.refreshWiFiNetworkState()
} }
} }
} }
@@ -4,6 +4,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/godbus/dbus/v5"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -168,6 +169,92 @@ func TestIWDBackend_MapIwdDBusError(t *testing.T) {
} }
} }
func TestIWDSavedWiFiProfilesFromManagedObjects(t *testing.T) {
objects := map[dbus.ObjectPath]map[string]map[string]dbus.Variant{
"/net/connman/iwd/known_network/1": {
iwdKnownNetworkInterface: {
"Name": dbus.MakeVariant("Home"),
"AutoConnect": dbus.MakeVariant(false),
"Hidden": dbus.MakeVariant(true),
"Type": dbus.MakeVariant("psk"),
},
},
"/net/connman/iwd/known_network/2": {
iwdKnownNetworkInterface: {
"Name": dbus.MakeVariant("Office"),
"Type": dbus.MakeVariant("8021x"),
},
},
"/net/connman/iwd/known_network/3": {
iwdKnownNetworkInterface: {
"Name": dbus.MakeVariant("Cafe"),
"Type": dbus.MakeVariant("open"),
},
},
"/net/connman/iwd/network/1": {
iwdNetworkInterface: {
"Name": dbus.MakeVariant("VisibleOnly"),
},
},
}
profiles := iwdSavedWiFiProfilesFromManagedObjects(objects)
assert.Len(t, profiles, 3)
assert.False(t, profiles["Home"].Autoconnect)
assert.True(t, profiles["Home"].Hidden)
assert.True(t, profiles["Home"].Secured)
assert.False(t, profiles["Home"].Enterprise)
assert.True(t, profiles["Office"].Autoconnect)
assert.True(t, profiles["Office"].Secured)
assert.True(t, profiles["Office"].Enterprise)
assert.True(t, profiles["Cafe"].Autoconnect)
assert.False(t, profiles["Cafe"].Secured)
assert.False(t, profiles["Cafe"].Enterprise)
}
func TestIWDWiFiNetworksFromVisibleIncludesConnectedHiddenFallback(t *testing.T) {
profiles := map[string]savedWiFiProfile{
"Home": {
Autoconnect: true,
Secured: true,
Hidden: true,
Mode: "infrastructure",
},
}
visible := []WiFiNetwork{
{
SSID: "Cafe",
Signal: 42,
Secured: false,
},
}
networks := iwdWiFiNetworksFromVisible(visible, profiles, "Home", true, 68)
savedNetworks := savedWiFiNetworksFromProfiles(profiles, map[string]WiFiNetwork{
networks[0].SSID: networks[0],
networks[1].SSID: networks[1],
}, "Home", true)
assert.Len(t, networks, 2)
assert.Equal(t, "Cafe", networks[0].SSID)
assert.False(t, networks[0].Connected)
assert.Equal(t, "Home", networks[1].SSID)
assert.True(t, networks[1].Connected)
assert.True(t, networks[1].Hidden)
assert.True(t, networks[1].Saved)
assert.True(t, networks[1].Autoconnect)
assert.Equal(t, uint8(68), networks[1].Signal)
assert.Len(t, savedNetworks, 1)
assert.Equal(t, "Home", savedNetworks[0].SSID)
assert.True(t, savedNetworks[0].Connected)
assert.False(t, savedNetworks[0].OutOfRange)
}
func TestConnectAttempt_Finalization(t *testing.T) { func TestConnectAttempt_Finalization(t *testing.T) {
backend, _ := NewIWDBackend() backend, _ := NewIWDBackend()
backend.state = &BackendState{} backend.state = &BackendState{}
+129 -46
View File
@@ -164,22 +164,18 @@ func (b *IWDBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
return nil, fmt.Errorf("failed to get networks: %w", err) return nil, fmt.Errorf("failed to get networks: %w", err)
} }
knownNetworks, err := b.getKnownNetworks() savedProfiles, err := b.getIWDSavedWiFiProfiles()
if err != nil { if err != nil {
knownNetworks = make(map[string]bool) savedProfiles = make(map[string]savedWiFiProfile)
}
autoconnectMap, err := b.getAutoconnectSettings()
if err != nil {
autoconnectMap = make(map[string]bool)
} }
b.stateMutex.RLock() b.stateMutex.RLock()
currentSSID := b.state.WiFiSSID currentSSID := b.state.WiFiSSID
wifiConnected := b.state.WiFiConnected wifiConnected := b.state.WiFiConnected
wifiSignal := b.state.WiFiSignal
b.stateMutex.RUnlock() b.stateMutex.RUnlock()
networks := make([]WiFiNetwork, 0, len(orderedNetworks)) visibleNetworks := make([]WiFiNetwork, 0, len(orderedNetworks))
for _, netData := range orderedNetworks { for _, netData := range orderedNetworks {
if len(netData) < 2 { if len(netData) < 2 {
continue continue
@@ -225,23 +221,26 @@ func (b *IWDBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
secured := netType != "open" secured := netType != "open"
network := WiFiNetwork{ visibleNetworks = append(visibleNetworks, WiFiNetwork{
SSID: name, SSID: name,
Signal: signal, Signal: signal,
Secured: secured, Secured: secured,
Connected: wifiConnected && name == currentSSID,
Saved: knownNetworks[name],
Autoconnect: autoconnectMap[name],
Enterprise: netType == "8021x", Enterprise: netType == "8021x",
})
} }
networks = append(networks, network) networks := iwdWiFiNetworksFromVisible(visibleNetworks, savedProfiles, currentSSID, wifiConnected, wifiSignal)
visibleNetworkMap := make(map[string]WiFiNetwork, len(networks))
for _, network := range networks {
visibleNetworkMap[network.SSID] = network
} }
savedNetworks := savedWiFiNetworksFromProfiles(savedProfiles, visibleNetworkMap, currentSSID, wifiConnected)
sortWiFiNetworks(networks) sortWiFiNetworks(networks)
b.stateMutex.Lock() b.stateMutex.Lock()
b.state.WiFiNetworks = networks b.state.WiFiNetworks = networks
b.state.SavedWiFiNetworks = savedNetworks
b.stateMutex.Unlock() b.stateMutex.Unlock()
now := time.Now() now := time.Now()
@@ -254,56 +253,138 @@ func (b *IWDBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
return networks, nil return networks, nil
} }
func (b *IWDBackend) getKnownNetworks() (map[string]bool, error) { func (b *IWDBackend) updateSavedWiFiNetworks() error {
obj := b.conn.Object(iwdBusName, iwdObjectPath) savedProfiles, err := b.getIWDSavedWiFiProfiles()
var objects map[dbus.ObjectPath]map[string]map[string]dbus.Variant
err := obj.Call(dbusObjectManager+".GetManagedObjects", 0).Store(&objects)
if err != nil { if err != nil {
return nil, err return err
} }
known := make(map[string]bool) b.stateMutex.RLock()
currentSSID := b.state.WiFiSSID
wifiConnected := b.state.WiFiConnected
wifiNetworks := append([]WiFiNetwork(nil), b.state.WiFiNetworks...)
b.stateMutex.RUnlock()
wifiNetworks, savedNetworks := refreshSavedWiFiState(wifiNetworks, savedProfiles, currentSSID, wifiConnected)
b.stateMutex.Lock()
b.state.WiFiNetworks = wifiNetworks
b.state.SavedWiFiNetworks = savedNetworks
b.stateMutex.Unlock()
return nil
}
func iwdWiFiNetworksFromVisible(visibleNetworks []WiFiNetwork, savedProfiles map[string]savedWiFiProfile, currentSSID string, wifiConnected bool, wifiSignal uint8) []WiFiNetwork {
networks := make([]WiFiNetwork, 0, len(visibleNetworks)+1)
seenSSIDs := make(map[string]struct{}, len(visibleNetworks)+1)
for _, network := range visibleNetworks {
profile, saved := savedProfiles[network.SSID]
network.Connected = wifiConnected && network.SSID == currentSSID
network.Saved = saved
network.Autoconnect = profile.Autoconnect
network.Hidden = network.Hidden || profile.Hidden
network.Secured = network.Secured || profile.Secured
network.Enterprise = network.Enterprise || profile.Enterprise
if network.Mode == "" {
network.Mode = profile.Mode
}
networks = append(networks, network)
seenSSIDs[network.SSID] = struct{}{}
}
if wifiConnected && currentSSID != "" {
if _, exists := seenSSIDs[currentSSID]; !exists {
profile, saved := savedProfiles[currentSSID]
secured := profile.Secured
if !saved {
secured = true
}
mode := profile.Mode
if mode == "" {
mode = "infrastructure"
}
networks = append(networks, WiFiNetwork{
SSID: currentSSID,
Signal: wifiSignal,
Secured: secured,
Enterprise: profile.Enterprise,
Connected: true,
Saved: saved,
Autoconnect: profile.Autoconnect,
Hidden: true,
Mode: mode,
})
}
}
return networks
}
func iwdSavedWiFiProfilesFromManagedObjects(objects map[dbus.ObjectPath]map[string]map[string]dbus.Variant) map[string]savedWiFiProfile {
profiles := make(map[string]savedWiFiProfile)
for _, interfaces := range objects { for _, interfaces := range objects {
if knownProps, ok := interfaces[iwdKnownNetworkInterface]; ok { knownProps, ok := interfaces[iwdKnownNetworkInterface]
if nameVar, ok := knownProps["Name"]; ok { if !ok {
if name, ok := nameVar.Value().(string); ok { continue
known[name] = true
}
}
}
} }
return known, nil nameVar, ok := knownProps["Name"]
if !ok {
continue
}
name, ok := nameVar.Value().(string)
if !ok || name == "" {
continue
} }
func (b *IWDBackend) getAutoconnectSettings() (map[string]bool, error) { profile := savedWiFiProfile{
obj := b.conn.Object(iwdBusName, iwdObjectPath) Autoconnect: true,
Mode: "infrastructure",
var objects map[dbus.ObjectPath]map[string]map[string]dbus.Variant
err := obj.Call(dbusObjectManager+".GetManagedObjects", 0).Store(&objects)
if err != nil {
return nil, err
} }
autoconnectMap := make(map[string]bool)
for _, interfaces := range objects {
if knownProps, ok := interfaces[iwdKnownNetworkInterface]; ok {
if nameVar, ok := knownProps["Name"]; ok {
if name, ok := nameVar.Value().(string); ok {
autoconnect := true
if acVar, ok := knownProps["AutoConnect"]; ok { if acVar, ok := knownProps["AutoConnect"]; ok {
if ac, ok := acVar.Value().(bool); ok { if autoconnect, ok := acVar.Value().(bool); ok {
autoconnect = ac profile.Autoconnect = autoconnect
} }
} }
autoconnectMap[name] = autoconnect if hiddenVar, ok := knownProps["Hidden"]; ok {
if hidden, ok := hiddenVar.Value().(bool); ok {
profile.Hidden = hidden
} }
} }
if typeVar, ok := knownProps["Type"]; ok {
if networkType, ok := typeVar.Value().(string); ok {
profile.Secured = networkType != "" && networkType != "open"
profile.Enterprise = networkType == "8021x"
} }
} }
return autoconnectMap, nil if existing, ok := profiles[name]; ok {
profile.Autoconnect = profile.Autoconnect || existing.Autoconnect
profile.Hidden = profile.Hidden || existing.Hidden
profile.Secured = profile.Secured || existing.Secured
profile.Enterprise = profile.Enterprise || existing.Enterprise
}
profiles[name] = profile
}
return profiles
}
func (b *IWDBackend) getIWDSavedWiFiProfiles() (map[string]savedWiFiProfile, error) {
obj := b.conn.Object(iwdBusName, iwdObjectPath)
var objects map[dbus.ObjectPath]map[string]map[string]dbus.Variant
err := obj.Call(dbusObjectManager+".GetManagedObjects", 0).Store(&objects)
if err != nil {
return nil, err
}
return iwdSavedWiFiProfilesFromManagedObjects(objects), nil
} }
func (b *IWDBackend) GetWiFiNetworkDetails(ssid string) (*NetworkInfoResponse, error) { func (b *IWDBackend) GetWiFiNetworkDetails(ssid string) (*NetworkInfoResponse, error) {
@@ -614,6 +695,8 @@ func (b *IWDBackend) ForgetWiFiNetwork(ssid string) error {
b.stateMutex.Unlock() b.stateMutex.Unlock()
} }
_, _ = b.updateWiFiNetworks()
if b.onStateChange != nil { if b.onStateChange != nil {
b.onStateChange() b.onStateChange()
} }
@@ -222,6 +222,10 @@ func (b *NetworkManagerBackend) Initialize() error {
log.Warnf("Failed to update WiFi state: %v", err) log.Warnf("Failed to update WiFi state: %v", err)
} }
if err := b.updateSavedWiFiNetworks(); err != nil {
log.Warnf("Failed to get initial saved WiFi networks: %v", err)
}
if wifiEnabled { if wifiEnabled {
if _, err := b.updateWiFiNetworks(); err != nil { if _, err := b.updateWiFiNetworks(); err != nil {
log.Warnf("Failed to get initial networks: %v", err) log.Warnf("Failed to get initial networks: %v", err)
@@ -261,6 +265,7 @@ func (b *NetworkManagerBackend) GetCurrentState() (*BackendState, error) {
state := *b.state state := *b.state
state.WiFiNetworks = append([]WiFiNetwork(nil), b.state.WiFiNetworks...) state.WiFiNetworks = append([]WiFiNetwork(nil), b.state.WiFiNetworks...)
state.SavedWiFiNetworks = append([]WiFiNetwork(nil), b.state.SavedWiFiNetworks...)
state.WiFiDevices = append([]WiFiDevice(nil), b.state.WiFiDevices...) state.WiFiDevices = append([]WiFiDevice(nil), b.state.WiFiDevices...)
state.WiredConnections = append([]WiredConnection(nil), b.state.WiredConnections...) state.WiredConnections = append([]WiredConnection(nil), b.state.WiredConnections...)
state.EthernetDevices = append([]EthernetDevice(nil), b.state.EthernetDevices...) state.EthernetDevices = append([]EthernetDevice(nil), b.state.EthernetDevices...)
@@ -5,6 +5,12 @@ import (
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
const (
dbusNMSettingsPath = "/org/freedesktop/NetworkManager/Settings"
dbusNMSettingsInterface = "org.freedesktop.NetworkManager.Settings"
dbusNMSettingsConnectionInterface = "org.freedesktop.NetworkManager.Settings.Connection"
)
func (b *NetworkManagerBackend) startSignalPump() error { func (b *NetworkManagerBackend) startSignalPump() error {
conn, err := dbus.ConnectSystemBus() conn, err := dbus.ConnectSystemBus()
if err != nil { if err != nil {
@@ -27,8 +33,8 @@ func (b *NetworkManagerBackend) startSignalPump() error {
} }
if err := conn.AddMatchSignal( if err := conn.AddMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath("/org/freedesktop/NetworkManager/Settings")), dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface("org.freedesktop.NetworkManager.Settings"), dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("NewConnection"), dbus.WithMatchMember("NewConnection"),
); err != nil { ); err != nil {
conn.RemoveMatchSignal( conn.RemoveMatchSignal(
@@ -42,8 +48,8 @@ func (b *NetworkManagerBackend) startSignalPump() error {
} }
if err := conn.AddMatchSignal( if err := conn.AddMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath("/org/freedesktop/NetworkManager/Settings")), dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface("org.freedesktop.NetworkManager.Settings"), dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("ConnectionRemoved"), dbus.WithMatchMember("ConnectionRemoved"),
); err != nil { ); err != nil {
conn.RemoveMatchSignal( conn.RemoveMatchSignal(
@@ -52,8 +58,8 @@ func (b *NetworkManagerBackend) startSignalPump() error {
dbus.WithMatchMember("PropertiesChanged"), dbus.WithMatchMember("PropertiesChanged"),
) )
conn.RemoveMatchSignal( conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath("/org/freedesktop/NetworkManager/Settings")), dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface("org.freedesktop.NetworkManager.Settings"), dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("NewConnection"), dbus.WithMatchMember("NewConnection"),
) )
conn.RemoveSignal(signals) conn.RemoveSignal(signals)
@@ -61,6 +67,31 @@ func (b *NetworkManagerBackend) startSignalPump() error {
return err return err
} }
if err := conn.AddMatchSignal(
dbus.WithMatchPathNamespace(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface(dbusNMSettingsConnectionInterface),
dbus.WithMatchMember("Updated"),
); err != nil {
conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("NewConnection"),
)
conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("ConnectionRemoved"),
)
conn.RemoveSignal(signals)
conn.Close()
return err
}
if err := conn.AddMatchSignal( if err := conn.AddMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)), dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
dbus.WithMatchInterface(dbusNMInterface), dbus.WithMatchInterface(dbusNMInterface),
@@ -137,6 +168,32 @@ func (b *NetworkManagerBackend) stopSignalPump() {
dbus.WithMatchMember("PropertiesChanged"), dbus.WithMatchMember("PropertiesChanged"),
) )
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("NewConnection"),
)
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface(dbusNMSettingsInterface),
dbus.WithMatchMember("ConnectionRemoved"),
)
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchPathNamespace(dbus.ObjectPath(dbusNMSettingsPath)),
dbus.WithMatchInterface(dbusNMSettingsConnectionInterface),
dbus.WithMatchMember("Updated"),
)
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
dbus.WithMatchInterface(dbusNMInterface),
dbus.WithMatchMember("DeviceAdded"),
)
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
dbus.WithMatchInterface(dbusNMInterface),
dbus.WithMatchMember("DeviceRemoved"),
)
for _, info := range b.wifiDevices { for _, info := range b.wifiDevices {
b.dbusConn.RemoveMatchSignal( b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(info.device.GetPath())), dbus.WithMatchObjectPath(dbus.ObjectPath(info.device.GetPath())),
@@ -164,9 +221,13 @@ func (b *NetworkManagerBackend) stopSignalPump() {
} }
func (b *NetworkManagerBackend) handleDBusSignal(sig *dbus.Signal) { func (b *NetworkManagerBackend) handleDBusSignal(sig *dbus.Signal) {
if sig.Name == "org.freedesktop.NetworkManager.Settings.NewConnection" || if sig.Name == dbusNMSettingsInterface+".NewConnection" ||
sig.Name == "org.freedesktop.NetworkManager.Settings.ConnectionRemoved" { sig.Name == dbusNMSettingsInterface+".ConnectionRemoved" ||
sig.Name == dbusNMSettingsConnectionInterface+".Updated" {
b.ListVPNProfiles() b.ListVPNProfiles()
if err := b.updateSavedWiFiNetworks(); err != nil {
b.updateWiFiNetworks()
}
if b.onStateChange != nil { if b.onStateChange != nil {
b.onStateChange() b.onStateChange()
} }
@@ -225,24 +225,14 @@ func (b *NetworkManagerBackend) GetWiFiQRCodeContent(ssid string) (string, error
return "", fmt.Errorf("failed to identify security type of network `%s`", ssid) return "", fmt.Errorf("failed to identify security type of network `%s`", ssid)
} }
var securityType string
switch keyMgmt { switch keyMgmt {
case "none": case "none":
authAlg, _ := secSettings["auth-alg"].(string) return "", fmt.Errorf("QR code generation only supports WPA-PSK connections, `%s` is open or WEP", ssid)
switch authAlg {
case "open":
securityType = "nopass"
default:
securityType = "WEP"
}
case "ieee8021x": case "ieee8021x":
securityType = "WEP" return "", fmt.Errorf("QR code generation only supports WPA-PSK connections, `%s` is enterprise", ssid)
case "wpa-psk", "sae", "wpa-psk-sae":
default: default:
securityType = "WPA" return "", fmt.Errorf("QR code generation only supports WPA-PSK connections, `%s` uses %s", ssid, keyMgmt)
}
if securityType != "WPA" {
return "", fmt.Errorf("QR code generation only supports WPA connections, `%s` uses %s", ssid, securityType)
} }
var psk string var psk string
@@ -276,7 +266,7 @@ func (b *NetworkManagerBackend) GetWiFiQRCodeContent(ssid string) (string, error
return "", fmt.Errorf("failed to retrieve password for `%s`", ssid) return "", fmt.Errorf("failed to retrieve password for `%s`", ssid)
} }
return FormatWiFiQRString(securityType, ssid, psk), nil return FormatWiFiQRString("WPA", ssid, psk), nil
} }
func (b *NetworkManagerBackend) ConnectWiFi(req ConnectionRequest) error { func (b *NetworkManagerBackend) ConnectWiFi(req ConnectionRequest) error {
@@ -405,6 +395,74 @@ func (b *NetworkManagerBackend) ForgetWiFiNetwork(ssid string) error {
return nil return nil
} }
func getSavedWiFiProfiles(connections []gonetworkmanager.Connection) map[string]savedWiFiProfile {
profiles := make(map[string]savedWiFiProfile)
for _, conn := range connections {
connSettings, err := conn.GetSettings()
if err != nil {
continue
}
connMeta, ok := connSettings["connection"]
if !ok {
continue
}
connType, ok := connMeta["type"].(string)
if !ok || connType != "802-11-wireless" {
continue
}
wifiSettings, ok := connSettings["802-11-wireless"]
if !ok {
continue
}
ssidBytes, ok := wifiSettings["ssid"].([]byte)
if !ok || len(ssidBytes) == 0 {
continue
}
ssid := string(ssidBytes)
profile := savedWiFiProfile{
Autoconnect: true,
Mode: "infrastructure",
}
if ac, ok := connMeta["autoconnect"].(bool); ok {
profile.Autoconnect = ac
}
if hidden, ok := wifiSettings["hidden"].(bool); ok {
profile.Hidden = hidden
}
if mode, ok := wifiSettings["mode"].(string); ok && mode != "" {
profile.Mode = mode
}
if _, ok := connSettings["802-11-wireless-security"]; ok {
profile.Secured = true
}
if _, ok := connSettings["802-1x"]; ok {
profile.Enterprise = true
profile.Secured = true
}
if existing, ok := profiles[ssid]; ok {
profile.Autoconnect = profile.Autoconnect || existing.Autoconnect
profile.Hidden = profile.Hidden || existing.Hidden
profile.Secured = profile.Secured || existing.Secured
profile.Enterprise = profile.Enterprise || existing.Enterprise
if profile.Mode == "" {
profile.Mode = existing.Mode
}
}
profiles[ssid] = profile
}
return profiles
}
func (b *NetworkManagerBackend) IsConnectingTo(ssid string) bool { func (b *NetworkManagerBackend) IsConnectingTo(ssid string) bool {
b.stateMutex.RLock() b.stateMutex.RLock()
defer b.stateMutex.RUnlock() defer b.stateMutex.RUnlock()
@@ -442,47 +500,7 @@ func (b *NetworkManagerBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
return nil, fmt.Errorf("failed to get connections: %w", err) return nil, fmt.Errorf("failed to get connections: %w", err)
} }
savedSSIDs := make(map[string]bool) savedProfiles := getSavedWiFiProfiles(connections)
autoconnectMap := make(map[string]bool)
hiddenSSIDs := make(map[string]bool)
for _, conn := range connections {
connSettings, err := conn.GetSettings()
if err != nil {
continue
}
connMeta, ok := connSettings["connection"]
if !ok {
continue
}
connType, ok := connMeta["type"].(string)
if !ok || connType != "802-11-wireless" {
continue
}
wifiSettings, ok := connSettings["802-11-wireless"]
if !ok {
continue
}
ssidBytes, ok := wifiSettings["ssid"].([]byte)
if !ok {
continue
}
ssid := string(ssidBytes)
savedSSIDs[ssid] = true
autoconnect := true
if ac, ok := connMeta["autoconnect"].(bool); ok {
autoconnect = ac
}
autoconnectMap[ssid] = autoconnect
if hidden, ok := wifiSettings["hidden"].(bool); ok && hidden {
hiddenSSIDs[ssid] = true
}
}
b.stateMutex.RLock() b.stateMutex.RLock()
currentSSID := b.state.WiFiSSID currentSSID := b.state.WiFiSSID
@@ -491,8 +509,8 @@ func (b *NetworkManagerBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
wifiBSSID := b.state.WiFiBSSID wifiBSSID := b.state.WiFiBSSID
b.stateMutex.RUnlock() b.stateMutex.RUnlock()
seenSSIDs := make(map[string]*WiFiNetwork) seenSSIDs := make(map[string]int)
networks := []WiFiNetwork{} networks := make([]WiFiNetwork, 0, len(apPaths)+1)
for _, ap := range apPaths { for _, ap := range apPaths {
ssid, err := ap.GetPropertySSID() ssid, err := ap.GetPropertySSID()
@@ -500,7 +518,8 @@ func (b *NetworkManagerBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
continue continue
} }
if existing, exists := seenSSIDs[ssid]; exists { if existingIndex, exists := seenSSIDs[ssid]; exists {
existing := &networks[existingIndex]
strength, _ := ap.GetPropertyStrength() strength, _ := ap.GetPropertyStrength()
if strength > existing.Signal { if strength > existing.Signal {
existing.Signal = strength existing.Signal = strength
@@ -550,6 +569,7 @@ func (b *NetworkManagerBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
} }
} }
profile, saved := savedProfiles[ssid]
network := WiFiNetwork{ network := WiFiNetwork{
SSID: ssid, SSID: ssid,
BSSID: bssid, BSSID: bssid,
@@ -557,45 +577,86 @@ func (b *NetworkManagerBackend) updateWiFiNetworks() ([]WiFiNetwork, error) {
Secured: secured, Secured: secured,
Enterprise: enterprise, Enterprise: enterprise,
Connected: isConnected, Connected: isConnected,
Saved: savedSSIDs[ssid], Saved: saved,
Autoconnect: autoconnectMap[ssid], Autoconnect: profile.Autoconnect,
Hidden: hiddenSSIDs[ssid], Hidden: profile.Hidden,
Frequency: freq, Frequency: freq,
Mode: modeStr, Mode: modeStr,
Rate: rate, Rate: rate,
Channel: channel, Channel: channel,
} }
seenSSIDs[ssid] = &network
networks = append(networks, network) networks = append(networks, network)
seenSSIDs[ssid] = len(networks) - 1
} }
if wifiConnected && currentSSID != "" { if wifiConnected && currentSSID != "" {
if _, exists := seenSSIDs[currentSSID]; !exists { if _, exists := seenSSIDs[currentSSID]; !exists {
profile, saved := savedProfiles[currentSSID]
hiddenNetwork := WiFiNetwork{ hiddenNetwork := WiFiNetwork{
SSID: currentSSID, SSID: currentSSID,
BSSID: wifiBSSID, BSSID: wifiBSSID,
Signal: wifiSignal, Signal: wifiSignal,
Secured: true, Secured: true,
Connected: true, Connected: true,
Saved: savedSSIDs[currentSSID], Saved: saved,
Autoconnect: autoconnectMap[currentSSID], Autoconnect: profile.Autoconnect,
Hidden: true, Hidden: true,
Mode: "infrastructure", Mode: "infrastructure",
} }
networks = append(networks, hiddenNetwork) networks = append(networks, hiddenNetwork)
seenSSIDs[currentSSID] = len(networks) - 1
} }
} }
visibleNetworks := wiFiNetworksBySSID(networks, true)
savedNetworks := savedWiFiNetworksFromProfiles(savedProfiles, visibleNetworks, currentSSID, wifiConnected)
sortWiFiNetworks(networks) sortWiFiNetworks(networks)
b.stateMutex.Lock() b.stateMutex.Lock()
b.state.WiFiNetworks = networks b.state.WiFiNetworks = networks
b.state.SavedWiFiNetworks = savedNetworks
b.stateMutex.Unlock() b.stateMutex.Unlock()
return networks, nil return networks, nil
} }
func (b *NetworkManagerBackend) updateSavedWiFiNetworks() error {
s := b.settings
if s == nil {
var err error
s, err = gonetworkmanager.NewSettings()
if err != nil {
return fmt.Errorf("failed to get settings: %w", err)
}
b.settings = s
}
settingsMgr := s.(gonetworkmanager.Settings)
connections, err := settingsMgr.ListConnections()
if err != nil {
return fmt.Errorf("failed to get connections: %w", err)
}
savedProfiles := getSavedWiFiProfiles(connections)
b.stateMutex.RLock()
currentSSID := b.state.WiFiSSID
wifiConnected := b.state.WiFiConnected
wifiNetworks := append([]WiFiNetwork(nil), b.state.WiFiNetworks...)
b.stateMutex.RUnlock()
wifiNetworks, savedNetworks := refreshSavedWiFiState(wifiNetworks, savedProfiles, currentSSID, wifiConnected)
b.stateMutex.Lock()
b.state.WiFiNetworks = wifiNetworks
b.state.SavedWiFiNetworks = savedNetworks
b.stateMutex.Unlock()
return nil
}
func (b *NetworkManagerBackend) findConnection(ssid string) (gonetworkmanager.Connection, error) { func (b *NetworkManagerBackend) findConnection(ssid string) (gonetworkmanager.Connection, error) {
s := b.settings s := b.settings
if s == nil { if s == nil {
@@ -975,49 +1036,14 @@ func (b *NetworkManagerBackend) updateAllWiFiDevices() {
return return
} }
savedSSIDs := make(map[string]bool) savedProfiles := getSavedWiFiProfiles(connections)
autoconnectMap := make(map[string]bool)
hiddenSSIDs := make(map[string]bool)
for _, conn := range connections {
connSettings, err := conn.GetSettings()
if err != nil {
continue
}
connMeta, ok := connSettings["connection"]
if !ok {
continue
}
connType, ok := connMeta["type"].(string)
if !ok || connType != "802-11-wireless" {
continue
}
wifiSettings, ok := connSettings["802-11-wireless"]
if !ok {
continue
}
ssidBytes, ok := wifiSettings["ssid"].([]byte)
if !ok {
continue
}
ssid := string(ssidBytes)
savedSSIDs[ssid] = true
autoconnect := true
if ac, ok := connMeta["autoconnect"].(bool); ok {
autoconnect = ac
}
autoconnectMap[ssid] = autoconnect
if hidden, ok := wifiSettings["hidden"].(bool); ok && hidden {
hiddenSSIDs[ssid] = true
}
}
var devices []WiFiDevice var devices []WiFiDevice
visibleNetworks := make(map[string]WiFiNetwork)
b.stateMutex.RLock()
currentSSID := b.state.WiFiSSID
wifiConnected := b.state.WiFiConnected
b.stateMutex.RUnlock()
for name, devInfo := range b.wifiDevices { for name, devInfo := range b.wifiDevices {
state, _ := devInfo.device.GetPropertyState() state, _ := devInfo.device.GetPropertyState()
@@ -1050,14 +1076,16 @@ func (b *NetworkManagerBackend) updateAllWiFiDevices() {
apPaths, err := devInfo.wireless.GetAccessPoints() apPaths, err := devInfo.wireless.GetAccessPoints()
var networks []WiFiNetwork var networks []WiFiNetwork
if err == nil { if err == nil {
seenSSIDs := make(map[string]*WiFiNetwork) seenSSIDs := make(map[string]int)
networks = make([]WiFiNetwork, 0, len(apPaths)+1)
for _, ap := range apPaths { for _, ap := range apPaths {
apSSID, err := ap.GetPropertySSID() apSSID, err := ap.GetPropertySSID()
if err != nil || apSSID == "" { if err != nil || apSSID == "" {
continue continue
} }
if existing, exists := seenSSIDs[apSSID]; exists { if existingIndex, exists := seenSSIDs[apSSID]; exists {
existing := &networks[existingIndex]
strength, _ := ap.GetPropertyStrength() strength, _ := ap.GetPropertyStrength()
if strength > existing.Signal { if strength > existing.Signal {
existing.Signal = strength existing.Signal = strength
@@ -1107,6 +1135,7 @@ func (b *NetworkManagerBackend) updateAllWiFiDevices() {
} }
} }
profile, saved := savedProfiles[apSSID]
network := WiFiNetwork{ network := WiFiNetwork{
SSID: apSSID, SSID: apSSID,
BSSID: apBSSID, BSSID: apBSSID,
@@ -1114,9 +1143,9 @@ func (b *NetworkManagerBackend) updateAllWiFiDevices() {
Secured: secured, Secured: secured,
Enterprise: enterprise, Enterprise: enterprise,
Connected: isConnected, Connected: isConnected,
Saved: savedSSIDs[apSSID], Saved: saved,
Autoconnect: autoconnectMap[apSSID], Autoconnect: profile.Autoconnect,
Hidden: hiddenSSIDs[apSSID], Hidden: profile.Hidden,
Frequency: freq, Frequency: freq,
Mode: modeStr, Mode: modeStr,
Rate: rate, Rate: rate,
@@ -1124,25 +1153,31 @@ func (b *NetworkManagerBackend) updateAllWiFiDevices() {
Device: name, Device: name,
} }
seenSSIDs[apSSID] = &network
networks = append(networks, network) networks = append(networks, network)
seenSSIDs[apSSID] = len(networks) - 1
if existing, ok := visibleNetworks[apSSID]; !ok || network.Signal > existing.Signal {
visibleNetworks[apSSID] = network
}
} }
if connected && ssid != "" { if connected && ssid != "" {
if _, exists := seenSSIDs[ssid]; !exists { if _, exists := seenSSIDs[ssid]; !exists {
profile, saved := savedProfiles[ssid]
hiddenNetwork := WiFiNetwork{ hiddenNetwork := WiFiNetwork{
SSID: ssid, SSID: ssid,
BSSID: bssid, BSSID: bssid,
Signal: signal, Signal: signal,
Secured: true, Secured: true,
Connected: true, Connected: true,
Saved: savedSSIDs[ssid], Saved: saved,
Autoconnect: autoconnectMap[ssid], Autoconnect: profile.Autoconnect,
Hidden: true, Hidden: true,
Mode: "infrastructure", Mode: "infrastructure",
Device: name, Device: name,
} }
networks = append(networks, hiddenNetwork) networks = append(networks, hiddenNetwork)
seenSSIDs[ssid] = len(networks) - 1
visibleNetworks[ssid] = hiddenNetwork
} }
} }
@@ -1168,6 +1203,7 @@ func (b *NetworkManagerBackend) updateAllWiFiDevices() {
b.stateMutex.Lock() b.stateMutex.Lock()
b.state.WiFiDevices = devices b.state.WiFiDevices = devices
b.state.SavedWiFiNetworks = savedWiFiNetworksFromProfiles(savedProfiles, visibleNetworks, currentSSID, wifiConnected)
b.stateMutex.Unlock() b.stateMutex.Unlock()
} }
@@ -4,6 +4,7 @@ import (
"testing" "testing"
mock_gonetworkmanager "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/github.com/Wifx/gonetworkmanager/v2" mock_gonetworkmanager "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/github.com/Wifx/gonetworkmanager/v2"
"github.com/Wifx/gonetworkmanager/v2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -176,6 +177,54 @@ func TestNetworkManagerBackend_UpdateWiFiNetworks_NoDevice(t *testing.T) {
assert.Contains(t, err.Error(), "no WiFi device available") assert.Contains(t, err.Error(), "no WiFi device available")
} }
func TestNetworkManagerBackend_UpdateSavedWiFiNetworksPreservesVisibleSavedNetworks(t *testing.T) {
mockNM := mock_gonetworkmanager.NewMockNetworkManager(t)
mockSettings := mock_gonetworkmanager.NewMockSettings(t)
mockConn := mock_gonetworkmanager.NewMockConnection(t)
backend, err := NewNetworkManagerBackend(mockNM)
assert.NoError(t, err)
backend.settings = mockSettings
backend.stateMutex.Lock()
backend.state.WiFiNetworks = []WiFiNetwork{
{
SSID: "Home",
Signal: 76,
},
}
backend.stateMutex.Unlock()
settings := gonetworkmanager.ConnectionSettings{
"connection": {
"type": "802-11-wireless",
"autoconnect": true,
},
"802-11-wireless": {
"ssid": []byte("Home"),
},
"802-11-wireless-security": {},
}
mockSettings.EXPECT().ListConnections().Return([]gonetworkmanager.Connection{mockConn}, nil)
mockConn.EXPECT().GetSettings().Return(settings, nil)
err = backend.updateSavedWiFiNetworks()
assert.NoError(t, err)
backend.stateMutex.RLock()
savedNetworks := append([]WiFiNetwork(nil), backend.state.SavedWiFiNetworks...)
wifiNetworks := append([]WiFiNetwork(nil), backend.state.WiFiNetworks...)
backend.stateMutex.RUnlock()
assert.Len(t, wifiNetworks, 1)
assert.True(t, wifiNetworks[0].Saved)
assert.Len(t, savedNetworks, 1)
assert.Equal(t, "Home", savedNetworks[0].SSID)
assert.True(t, savedNetworks[0].Saved)
assert.False(t, savedNetworks[0].OutOfRange)
assert.Equal(t, uint8(76), savedNetworks[0].Signal)
}
func TestNetworkManagerBackend_FindConnection_NoSettings(t *testing.T) { func TestNetworkManagerBackend_FindConnection_NoSettings(t *testing.T) {
mockNM := mock_gonetworkmanager.NewMockNetworkManager(t) mockNM := mock_gonetworkmanager.NewMockNetworkManager(t)
+29 -1
View File
@@ -1,6 +1,7 @@
package network package network
import ( import (
"errors"
"fmt" "fmt"
"sync" "sync"
"time" "time"
@@ -10,6 +11,10 @@ import (
"github.com/yeqown/go-qrcode/writer/standard" "github.com/yeqown/go-qrcode/writer/standard"
) )
// ErrNoNetworkBackend is returned when no supported network management daemon
// (NetworkManager, iwd, systemd-networkd, ConnMan) is present on the system.
var ErrNoNetworkBackend = errors.New("no supported network backend found")
func NewManager() (*Manager, error) { func NewManager() (*Manager, error) {
detection, err := DetectNetworkStack() detection, err := DetectNetworkStack()
if err != nil { if err != nil {
@@ -58,7 +63,7 @@ func NewManager() (*Manager, error) {
} }
default: default:
return nil, fmt.Errorf("no supported network backend found: %s", detection.ChosenReason) return nil, fmt.Errorf("%w: %s", ErrNoNetworkBackend, detection.ChosenReason)
} }
m := &Manager{ m := &Manager{
@@ -67,6 +72,7 @@ func NewManager() (*Manager, error) {
NetworkStatus: StatusDisconnected, NetworkStatus: StatusDisconnected,
Preference: PreferenceAuto, Preference: PreferenceAuto,
WiFiNetworks: []WiFiNetwork{}, WiFiNetworks: []WiFiNetwork{},
SavedWiFiNetworks: []WiFiNetwork{},
}, },
stateMutex: sync.RWMutex{}, stateMutex: sync.RWMutex{},
@@ -120,6 +126,7 @@ func (m *Manager) syncStateFromBackend() error {
m.state.WiFiBSSID = backendState.WiFiBSSID m.state.WiFiBSSID = backendState.WiFiBSSID
m.state.WiFiSignal = backendState.WiFiSignal m.state.WiFiSignal = backendState.WiFiSignal
m.state.WiFiNetworks = backendState.WiFiNetworks m.state.WiFiNetworks = backendState.WiFiNetworks
m.state.SavedWiFiNetworks = backendState.SavedWiFiNetworks
m.state.WiFiDevices = backendState.WiFiDevices m.state.WiFiDevices = backendState.WiFiDevices
m.state.WiredConnections = backendState.WiredConnections m.state.WiredConnections = backendState.WiredConnections
m.state.VPNProfiles = backendState.VPNProfiles m.state.VPNProfiles = backendState.VPNProfiles
@@ -156,6 +163,7 @@ func (m *Manager) snapshotState() NetworkState {
defer m.stateMutex.RUnlock() defer m.stateMutex.RUnlock()
s := *m.state s := *m.state
s.WiFiNetworks = append([]WiFiNetwork(nil), m.state.WiFiNetworks...) s.WiFiNetworks = append([]WiFiNetwork(nil), m.state.WiFiNetworks...)
s.SavedWiFiNetworks = append([]WiFiNetwork(nil), m.state.SavedWiFiNetworks...)
s.WiFiDevices = append([]WiFiDevice(nil), m.state.WiFiDevices...) s.WiFiDevices = append([]WiFiDevice(nil), m.state.WiFiDevices...)
s.WiredConnections = append([]WiredConnection(nil), m.state.WiredConnections...) s.WiredConnections = append([]WiredConnection(nil), m.state.WiredConnections...)
s.EthernetDevices = append([]EthernetDevice(nil), m.state.EthernetDevices...) s.EthernetDevices = append([]EthernetDevice(nil), m.state.EthernetDevices...)
@@ -211,6 +219,9 @@ func stateChangedMeaningfully(old, new *NetworkState) bool {
if len(old.WiFiNetworks) != len(new.WiFiNetworks) { if len(old.WiFiNetworks) != len(new.WiFiNetworks) {
return true return true
} }
if len(old.SavedWiFiNetworks) != len(new.SavedWiFiNetworks) {
return true
}
if len(old.WiFiDevices) != len(new.WiFiDevices) { if len(old.WiFiDevices) != len(new.WiFiDevices) {
return true return true
} }
@@ -238,6 +249,23 @@ func stateChangedMeaningfully(old, new *NetworkState) bool {
} }
} }
for i := range old.SavedWiFiNetworks {
oldNet := &old.SavedWiFiNetworks[i]
newNet := &new.SavedWiFiNetworks[i]
if oldNet.SSID != newNet.SSID {
return true
}
if oldNet.Connected != newNet.Connected {
return true
}
if oldNet.Autoconnect != newNet.Autoconnect {
return true
}
if oldNet.OutOfRange != newNet.OutOfRange {
return true
}
}
for i := range old.WiredConnections { for i := range old.WiredConnections {
oldNet := &old.WiredConnections[i] oldNet := &old.WiredConnections[i]
newNet := &new.WiredConnections[i] newNet := &new.WiredConnections[i]
+2
View File
@@ -34,6 +34,7 @@ type WiFiNetwork struct {
Saved bool `json:"saved"` Saved bool `json:"saved"`
Autoconnect bool `json:"autoconnect"` Autoconnect bool `json:"autoconnect"`
Hidden bool `json:"hidden"` Hidden bool `json:"hidden"`
OutOfRange bool `json:"outOfRange"`
Frequency uint32 `json:"frequency"` Frequency uint32 `json:"frequency"`
Mode string `json:"mode"` Mode string `json:"mode"`
Rate uint32 `json:"rate"` Rate uint32 `json:"rate"`
@@ -111,6 +112,7 @@ type NetworkState struct {
WiFiBSSID string `json:"wifiBSSID"` WiFiBSSID string `json:"wifiBSSID"`
WiFiSignal uint8 `json:"wifiSignal"` WiFiSignal uint8 `json:"wifiSignal"`
WiFiNetworks []WiFiNetwork `json:"wifiNetworks"` WiFiNetworks []WiFiNetwork `json:"wifiNetworks"`
SavedWiFiNetworks []WiFiNetwork `json:"savedWifiNetworks"`
WiFiDevices []WiFiDevice `json:"wifiDevices"` WiFiDevices []WiFiDevice `json:"wifiDevices"`
WiredConnections []WiredConnection `json:"wiredConnections"` WiredConnections []WiredConnection `json:"wiredConnections"`
VPNProfiles []VPNProfile `json:"vpnProfiles"` VPNProfiles []VPNProfile `json:"vpnProfiles"`
+103
View File
@@ -0,0 +1,103 @@
package network
import "sort"
type savedWiFiProfile struct {
Autoconnect bool
Hidden bool
Secured bool
Enterprise bool
Mode string
}
// Saved WiFi state is keyed by SSID because the UI/API accepts SSID actions.
// Multiple backend profiles for the same SSID are intentionally collapsed here.
func mergeSavedProfilesIntoWiFiNetworks(networks []WiFiNetwork, profiles map[string]savedWiFiProfile, currentSSID string, wifiConnected bool) []WiFiNetwork {
merged := make([]WiFiNetwork, len(networks))
for i, network := range networks {
profile, saved := profiles[network.SSID]
network.Connected = wifiConnected && network.SSID == currentSSID
network.Saved = saved
if saved {
network.Autoconnect = profile.Autoconnect
network.Hidden = network.Hidden || profile.Hidden
network.Secured = network.Secured || profile.Secured
network.Enterprise = network.Enterprise || profile.Enterprise
if network.Mode == "" {
network.Mode = profile.Mode
}
} else {
network.Autoconnect = false
}
merged[i] = network
}
return merged
}
func wiFiNetworksBySSID(networks []WiFiNetwork, visibleOnly bool) map[string]WiFiNetwork {
visible := make(map[string]WiFiNetwork, len(networks))
for _, network := range networks {
if visibleOnly && network.OutOfRange {
continue
}
visible[network.SSID] = network
}
return visible
}
func refreshSavedWiFiState(networks []WiFiNetwork, profiles map[string]savedWiFiProfile, currentSSID string, wifiConnected bool) ([]WiFiNetwork, []WiFiNetwork) {
mergedNetworks := mergeSavedProfilesIntoWiFiNetworks(networks, profiles, currentSSID, wifiConnected)
visibleNetworks := wiFiNetworksBySSID(mergedNetworks, true)
savedNetworks := savedWiFiNetworksFromProfiles(profiles, visibleNetworks, currentSSID, wifiConnected)
return mergedNetworks, savedNetworks
}
func savedWiFiNetworksFromProfiles(profiles map[string]savedWiFiProfile, visible map[string]WiFiNetwork, currentSSID string, wifiConnected bool) []WiFiNetwork {
networks := make([]WiFiNetwork, 0, len(profiles))
for ssid, profile := range profiles {
if network, ok := visible[ssid]; ok {
network.Saved = true
network.Autoconnect = profile.Autoconnect
network.Hidden = network.Hidden || profile.Hidden
network.Secured = network.Secured || profile.Secured
network.Enterprise = network.Enterprise || profile.Enterprise
network.OutOfRange = false
if network.Mode == "" {
network.Mode = profile.Mode
}
networks = append(networks, network)
continue
}
isConnected := wifiConnected && ssid == currentSSID
networks = append(networks, WiFiNetwork{
SSID: ssid,
Secured: profile.Secured,
Enterprise: profile.Enterprise,
Connected: isConnected,
Saved: true,
Autoconnect: profile.Autoconnect,
Hidden: profile.Hidden,
OutOfRange: !isConnected,
Mode: profile.Mode,
})
}
sort.Slice(networks, func(i, j int) bool {
if networks[i].Connected && !networks[j].Connected {
return true
}
if !networks[i].Connected && networks[j].Connected {
return false
}
if networks[i].OutOfRange != networks[j].OutOfRange {
return !networks[i].OutOfRange
}
if networks[i].Signal != networks[j].Signal {
return networks[i].Signal > networks[j].Signal
}
return networks[i].SSID < networks[j].SSID
})
return networks
}
@@ -0,0 +1,170 @@
package network
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMergeSavedProfilesIntoWiFiNetworks(t *testing.T) {
networks := []WiFiNetwork{
{
SSID: "Home",
Signal: 80,
Secured: false,
Autoconnect: false,
},
{
SSID: "Cafe",
Signal: 50,
Secured: false,
Autoconnect: true,
},
}
profiles := map[string]savedWiFiProfile{
"Home": {
Autoconnect: true,
Hidden: true,
Secured: true,
Mode: "infrastructure",
},
}
merged := mergeSavedProfilesIntoWiFiNetworks(networks, profiles, "Home", true)
assert.Len(t, merged, 2)
assert.Equal(t, "Home", merged[0].SSID)
assert.True(t, merged[0].Connected)
assert.True(t, merged[0].Saved)
assert.True(t, merged[0].Autoconnect)
assert.True(t, merged[0].Hidden)
assert.True(t, merged[0].Secured)
assert.Equal(t, "infrastructure", merged[0].Mode)
assert.Equal(t, "Cafe", merged[1].SSID)
assert.False(t, merged[1].Saved)
assert.False(t, merged[1].Autoconnect)
}
func TestSavedWiFiNetworksFromProfilesOutOfRangeWithoutVisibleNetworks(t *testing.T) {
profiles := map[string]savedWiFiProfile{
"Home": {
Autoconnect: true,
Secured: true,
Mode: "infrastructure",
},
}
networks := savedWiFiNetworksFromProfiles(profiles, nil, "", false)
assert.Len(t, networks, 1)
assert.Equal(t, "Home", networks[0].SSID)
assert.True(t, networks[0].Saved)
assert.True(t, networks[0].OutOfRange)
assert.Equal(t, uint8(0), networks[0].Signal)
}
func TestSavedWiFiNetworksFromProfilesKeepsConnectedCurrentNetworkInRange(t *testing.T) {
profiles := map[string]savedWiFiProfile{
"Home": {
Autoconnect: true,
Secured: true,
},
}
networks := savedWiFiNetworksFromProfiles(profiles, nil, "Home", true)
assert.Len(t, networks, 1)
assert.Equal(t, "Home", networks[0].SSID)
assert.True(t, networks[0].Connected)
assert.False(t, networks[0].OutOfRange)
}
func TestSavedWiFiNetworksFromProfilesIncludesOutOfRange(t *testing.T) {
profiles := map[string]savedWiFiProfile{
"Home": {
Autoconnect: true,
Hidden: true,
Secured: true,
Mode: "infrastructure",
},
"Office": {
Autoconnect: false,
Secured: true,
Enterprise: true,
Mode: "infrastructure",
},
}
visible := map[string]WiFiNetwork{
"Home": {
SSID: "Home",
Signal: 72,
Secured: true,
Connected: true,
},
}
networks := savedWiFiNetworksFromProfiles(profiles, visible, "Home", true)
assert.Len(t, networks, 2)
assert.Equal(t, "Home", networks[0].SSID)
assert.True(t, networks[0].Saved)
assert.True(t, networks[0].Connected)
assert.False(t, networks[0].OutOfRange)
assert.True(t, networks[0].Hidden)
assert.Equal(t, uint8(72), networks[0].Signal)
assert.Equal(t, "Office", networks[1].SSID)
assert.True(t, networks[1].Saved)
assert.False(t, networks[1].Autoconnect)
assert.True(t, networks[1].Enterprise)
assert.True(t, networks[1].OutOfRange)
}
func TestWiFiNetworksBySSIDVisibleOnlySkipsOutOfRange(t *testing.T) {
visible := wiFiNetworksBySSID([]WiFiNetwork{
{SSID: "Home", Signal: 70},
{SSID: "Office", Signal: 0, OutOfRange: true},
}, true)
assert.Contains(t, visible, "Home")
assert.NotContains(t, visible, "Office")
}
func TestRefreshSavedWiFiStatePreservesVisibleSavedNetworks(t *testing.T) {
networks := []WiFiNetwork{
{
SSID: "Home",
Signal: 82,
},
}
profiles := map[string]savedWiFiProfile{
"Home": {
Autoconnect: true,
Secured: true,
Mode: "infrastructure",
},
"Office": {
Autoconnect: false,
Secured: true,
Mode: "infrastructure",
},
}
mergedNetworks, savedNetworks := refreshSavedWiFiState(networks, profiles, "", false)
assert.Len(t, mergedNetworks, 1)
assert.Equal(t, "Home", mergedNetworks[0].SSID)
assert.True(t, mergedNetworks[0].Saved)
assert.True(t, mergedNetworks[0].Autoconnect)
assert.Len(t, savedNetworks, 2)
assert.Equal(t, "Home", savedNetworks[0].SSID)
assert.True(t, savedNetworks[0].Saved)
assert.False(t, savedNetworks[0].OutOfRange)
assert.Equal(t, uint8(82), savedNetworks[0].Signal)
assert.Equal(t, "Office", savedNetworks[1].SSID)
assert.True(t, savedNetworks[1].Saved)
assert.True(t, savedNetworks[1].OutOfRange)
}
-10
View File
@@ -11,7 +11,6 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups"
serverDbus "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dbus" serverDbus "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dbus"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/dwl"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/freedesktop" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/freedesktop"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/location" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/location"
@@ -125,15 +124,6 @@ func RouteRequest(conn net.Conn, req models.Request) {
return return
} }
if strings.HasPrefix(req.Method, "dwl.") {
if dwlManager == nil {
models.RespondError(conn, req.ID, "dwl manager not initialized")
return
}
dwl.HandleRequest(conn, req, dwlManager)
return
}
if strings.HasPrefix(req.Method, "brightness.") { if strings.HasPrefix(req.Method, "brightness.") {
if brightnessManager == nil { if brightnessManager == nil {
models.RespondError(conn, req.ID, "brightness manager not initialized") models.RespondError(conn, req.ID, "brightness manager not initialized")
+21 -96
View File
@@ -3,6 +3,7 @@ package server
import ( import (
"bufio" "bufio"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
@@ -22,7 +23,6 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups"
serverDbus "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dbus" serverDbus "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dbus"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/dwl"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/freedesktop" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/freedesktop"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/location" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/location"
@@ -39,7 +39,7 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/pkg/syncmap" "github.com/AvengeMedia/DankMaterialShell/core/pkg/syncmap"
) )
const APIVersion = 24 const APIVersion = 26
var CLIVersion = "dev" var CLIVersion = "dev"
@@ -66,7 +66,6 @@ var bluezManager *bluez.Manager
var appPickerManager *apppicker.Manager var appPickerManager *apppicker.Manager
var cupsManager *cups.Manager var cupsManager *cups.Manager
var tailscaleManager *tailscale.Manager var tailscaleManager *tailscale.Manager
var dwlManager *dwl.Manager
var brightnessManager *brightness.Manager var brightnessManager *brightness.Manager
var wlrOutputManager *wlroutput.Manager var wlrOutputManager *wlroutput.Manager
var evdevManager *evdev.Manager var evdevManager *evdev.Manager
@@ -252,30 +251,6 @@ func InitializeCupsManager() error {
return nil return nil
} }
func InitializeDwlManager() error {
log.Info("Attempting to initialize DWL IPC...")
if wlContext == nil {
ctx, err := wlcontext.New()
if err != nil {
log.Errorf("Failed to create shared Wayland context: %v", err)
return err
}
wlContext = ctx
}
manager, err := dwl.NewManager(wlContext.Display())
if err != nil {
log.Debug("Failed to initialize dwl manager: %v", err)
return err
}
dwlManager = manager
log.Info("DWL IPC initialized successfully")
return nil
}
func InitializeBrightnessManager() error { func InitializeBrightnessManager() error {
manager, err := brightness.NewManager() manager, err := brightness.NewManager()
if err != nil { if err != nil {
@@ -468,10 +443,6 @@ func getCapabilities() Capabilities {
caps = append(caps, "tailscale") caps = append(caps, "tailscale")
} }
if dwlManager != nil {
caps = append(caps, "dwl")
}
if brightnessManager != nil { if brightnessManager != nil {
caps = append(caps, "brightness") caps = append(caps, "brightness")
} }
@@ -538,10 +509,6 @@ func getServerInfo() ServerInfo {
caps = append(caps, "tailscale") caps = append(caps, "tailscale")
} }
if dwlManager != nil {
caps = append(caps, "dwl")
}
if brightnessManager != nil { if brightnessManager != nil {
caps = append(caps, "brightness") caps = append(caps, "brightness")
} }
@@ -1046,38 +1013,6 @@ func handleSubscribe(conn net.Conn, req models.Request) {
}() }()
} }
if shouldSubscribe("dwl") && dwlManager != nil {
wg.Add(1)
dwlChan := dwlManager.Subscribe(clientID + "-dwl")
go func() {
defer wg.Done()
defer dwlManager.Unsubscribe(clientID + "-dwl")
initialState := dwlManager.GetState()
select {
case eventChan <- ServiceEvent{Service: "dwl", Data: initialState}:
case <-stopChan:
return
}
for {
select {
case state, ok := <-dwlChan:
if !ok {
return
}
select {
case eventChan <- ServiceEvent{Service: "dwl", Data: state}:
case <-stopChan:
return
}
case <-stopChan:
return
}
}
}()
}
if shouldSubscribe("brightness") && brightnessManager != nil { if shouldSubscribe("brightness") && brightnessManager != nil {
wg.Add(2) wg.Add(2)
brightnessStateChan := brightnessManager.Subscribe(clientID + "-brightness-state") brightnessStateChan := brightnessManager.Subscribe(clientID + "-brightness-state")
@@ -1333,9 +1268,6 @@ func cleanupManagers() {
if cupsManager != nil { if cupsManager != nil {
cupsManager.Close() cupsManager.Close()
} }
if dwlManager != nil {
dwlManager.Close()
}
if brightnessManager != nil { if brightnessManager != nil {
brightnessManager.Close() brightnessManager.Close()
} }
@@ -1502,19 +1434,6 @@ func Start(printDocs bool) error {
log.Info(" cups.resumePrinter - Resume printer (params: printerName)") log.Info(" cups.resumePrinter - Resume printer (params: printerName)")
log.Info(" cups.cancelJob - Cancel job (params: printerName, jobID)") log.Info(" cups.cancelJob - Cancel job (params: printerName, jobID)")
log.Info(" cups.purgeJobs - Cancel all jobs (params: printerName)") log.Info(" cups.purgeJobs - Cancel all jobs (params: printerName)")
log.Info("DWL:")
log.Info(" dwl.getState - Get current dwl state (tags, windows, layouts, keyboard)")
log.Info(" dwl.setTags - Set active tags (params: output, tagmask, toggleTagset)")
log.Info(" dwl.setClientTags - Set focused client tags (params: output, andTags, xorTags)")
log.Info(" dwl.setLayout - Set layout (params: output, index)")
log.Info(" dwl.subscribe - Subscribe to dwl state changes (streaming)")
log.Info(" Output state includes:")
log.Info(" - tags : Tag states (active, clients, focused)")
log.Info(" - layoutSymbol : Current layout name")
log.Info(" - title : Focused window title")
log.Info(" - appId : Focused window app ID")
log.Info(" - kbLayout : Current keyboard layout")
log.Info(" - keymode : Current keybind mode")
log.Info("Brightness:") log.Info("Brightness:")
log.Info(" brightness.getState - Get current brightness state for all devices") log.Info(" brightness.getState - Get current brightness state for all devices")
log.Info(" brightness.setBrightness - Set device brightness (params: device, percent)") log.Info(" brightness.setBrightness - Set device brightness (params: device, percent)")
@@ -1563,26 +1482,36 @@ func Start(printDocs bool) error {
log.Info("") log.Info("")
go func() { go func() {
switch err := InitializeNetworkManager(); {
case err == nil:
notifyCapabilityChange()
return
case errors.Is(err, network.ErrNoNetworkBackend):
log.Warn("No supported network backend present; skipping retries")
return
default:
log.Warnf("Network manager unavailable, will retry: %v", err)
}
ticker := time.NewTicker(30 * time.Second) ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop() defer ticker.Stop()
if err := InitializeNetworkManager(); err != nil { for range 10 {
log.Warnf("Network manager unavailable: %v", err) <-ticker.C
} else {
notifyCapabilityChange()
return
}
for range ticker.C {
if networkManager != nil { if networkManager != nil {
return return
} }
if err := InitializeNetworkManager(); err == nil { switch err := InitializeNetworkManager(); {
case err == nil:
log.Info("Network manager initialized") log.Info("Network manager initialized")
notifyCapabilityChange() notifyCapabilityChange()
return return
case errors.Is(err, network.ErrNoNetworkBackend):
log.Warn("No supported network backend present; stopping retries")
return
} }
} }
log.Warn("Network manager still unavailable after retries; giving up")
}() }()
loginctlReady := make(chan struct{}) loginctlReady := make(chan struct{})
@@ -1691,10 +1620,6 @@ func Start(printDocs bool) error {
log.Debugf("AppPicker manager unavailable: %v", err) log.Debugf("AppPicker manager unavailable: %v", err)
} }
if err := InitializeDwlManager(); err != nil {
log.Debugf("DWL manager unavailable: %v", err)
}
if err := InitializeWlrOutputManager(); err != nil { if err := InitializeWlrOutputManager(); err != nil {
log.Debugf("WlrOutput manager unavailable: %v", err) log.Debugf("WlrOutput manager unavailable: %v", err)
} }
+22 -5
View File
@@ -131,7 +131,9 @@ func (m *Manager) SetInterval(seconds int) {
} }
m.mu.Lock() m.mu.Lock()
m.state.IntervalSeconds = seconds m.state.IntervalSeconds = seconds
m.state.NextCheckUnix = time.Now().Unix() + int64(seconds)
m.mu.Unlock() m.mu.Unlock()
m.wake()
m.markDirty() m.markDirty()
} }
@@ -182,10 +184,12 @@ func (m *Manager) Cancel() {
func (m *Manager) Acquire() { func (m *Manager) Acquire() {
atomic.AddInt32(&m.acquireCount, 1) atomic.AddInt32(&m.acquireCount, 1)
select { m.mu.Lock()
case m.wakeSched <- struct{}{}: if m.state.NextCheckUnix == 0 {
default: m.state.NextCheckUnix = time.Now().Unix() + int64(m.state.IntervalSeconds)
} }
m.mu.Unlock()
m.wake()
} }
func (m *Manager) Release() { func (m *Manager) Release() {
@@ -194,6 +198,13 @@ func (m *Manager) Release() {
} }
} }
func (m *Manager) wake() {
select {
case m.wakeSched <- struct{}{}:
default:
}
}
func (m *Manager) scheduler() { func (m *Manager) scheduler() {
defer m.schedulerWG.Done() defer m.schedulerWG.Done()
for { for {
@@ -208,11 +219,17 @@ func (m *Manager) scheduler() {
m.mu.RLock() m.mu.RLock()
interval := m.state.IntervalSeconds interval := m.state.IntervalSeconds
next := m.state.NextCheckUnix
m.mu.RUnlock() m.mu.RUnlock()
if interval < minIntervalSeconds { if interval < minIntervalSeconds {
interval = minIntervalSeconds interval = minIntervalSeconds
} }
t := time.NewTimer(time.Duration(interval) * time.Second) now := time.Now().Unix()
if next == 0 {
next = now + int64(interval)
}
wait := max(time.Duration(next-now)*time.Second, 0)
t := time.NewTimer(wait)
select { select {
case <-m.stopChan: case <-m.stopChan:
t.Stop() t.Stop()
@@ -279,13 +296,13 @@ func (m *Manager) runRefresh(parent context.Context) {
m.state.Packages = append(m.state.Packages, r.pkgs...) m.state.Packages = append(m.state.Packages, r.pkgs...)
} }
m.state.Count = len(m.state.Packages) m.state.Count = len(m.state.Packages)
m.state.NextCheckUnix = now + int64(m.state.IntervalSeconds)
if firstErr != nil { if firstErr != nil {
m.state.Phase = PhaseError m.state.Phase = PhaseError
m.state.Error = &ErrorInfo{Code: ErrCodeBackendFailed, Message: firstErr.Error()} m.state.Error = &ErrorInfo{Code: ErrCodeBackendFailed, Message: firstErr.Error()}
} else { } else {
m.state.Phase = PhaseIdle m.state.Phase = PhaseIdle
m.state.LastSuccessUnix = now m.state.LastSuccessUnix = now
m.state.NextCheckUnix = now + int64(m.state.IntervalSeconds)
} }
m.mu.Unlock() m.mu.Unlock()
m.markDirty() m.markDirty()
+1
View File
@@ -73,6 +73,7 @@ func convertPeerStatus(ps *ipnstate.PeerStatus, users map[tailcfg.UserID]tailcfg
Online: ps.Online, Online: ps.Online,
Active: ps.Active, Active: ps.Active,
ExitNode: ps.ExitNode, ExitNode: ps.ExitNode,
ExitNodeOption: ps.ExitNodeOption,
Relay: ps.Relay, Relay: ps.Relay,
RxBytes: ps.RxBytes, RxBytes: ps.RxBytes,
TxBytes: ps.TxBytes, TxBytes: ps.TxBytes,
@@ -14,6 +14,14 @@ func HandleRequest(conn net.Conn, req models.Request, manager *Manager) {
handleGetStatus(conn, req, manager) handleGetStatus(conn, req, manager)
case "tailscale.refresh": case "tailscale.refresh":
handleRefresh(conn, req, manager) handleRefresh(conn, req, manager)
case "tailscale.connect":
handleConnect(conn, req, manager)
case "tailscale.disconnect":
handleDisconnect(conn, req, manager)
case "tailscale.setExitNode":
handleSetExitNode(conn, req, manager)
case "tailscale.setAllowLanAccess":
handleSetAllowLanAccess(conn, req, manager)
default: default:
models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method)) models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method))
} }
@@ -28,3 +36,37 @@ func handleRefresh(conn net.Conn, req models.Request, manager *Manager) {
manager.RefreshState() manager.RefreshState()
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "refreshed"}) models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "refreshed"})
} }
func handleConnect(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.Connect(); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "connected"})
}
func handleDisconnect(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.Disconnect(); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "disconnected"})
}
func handleSetExitNode(conn net.Conn, req models.Request, manager *Manager) {
id := models.GetOr(req, "id", "")
if err := manager.SetExitNode(id); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "exit node updated"})
}
func handleSetAllowLanAccess(conn net.Conn, req models.Request, manager *Manager) {
enabled := models.GetOr(req, "enabled", false)
if err := manager.SetAllowLANAccess(enabled); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "lan access updated"})
}
@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"net" "net"
"testing" "testing"
"time" "time"
@@ -78,6 +79,63 @@ func TestHandleRefresh(t *testing.T) {
assert.True(t, resp.Result.Success) assert.True(t, resp.Result.Success)
} }
func TestHandleActions(t *testing.T) {
cases := []struct {
name string
method string
params map[string]any
}{
{"connect", "tailscale.connect", nil},
{"disconnect", "tailscale.disconnect", nil},
{"setExitNode", "tailscale.setExitNode", map[string]any{"id": "nABC123"}},
{"clearExitNode", "tailscale.setExitNode", map[string]any{"id": ""}},
{"setAllowLanAccess", "tailscale.setAllowLanAccess", map[string]any{"enabled": true}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
m := handlerTestManager()
defer m.Close()
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := models.Request{ID: 1, Method: tc.method, Params: tc.params}
HandleRequest(conn, req, m)
var resp models.Response[models.SuccessResult]
require.NoError(t, json.NewDecoder(buf).Decode(&resp))
assert.Equal(t, 1, resp.ID)
assert.Empty(t, resp.Error)
require.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
})
}
}
func TestHandleAction_BackendError(t *testing.T) {
client := &mockClient{
watchFn: blockingWatch,
statusFn: func(ctx context.Context) (*ipnstate.Status, error) { return runningStatus(), nil },
editPrefsFn: func(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
return nil, fmt.Errorf("backend rejected edit")
},
}
m := newManager(client)
defer m.Close()
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := models.Request{ID: 1, Method: "tailscale.connect"}
HandleRequest(conn, req, m)
var resp models.Response[models.SuccessResult]
require.NoError(t, json.NewDecoder(buf).Decode(&resp))
assert.Nil(t, resp.Result)
assert.Contains(t, resp.Error, "backend rejected edit")
}
func TestHandleRequest_UnknownMethod(t *testing.T) { func TestHandleRequest_UnknownMethod(t *testing.T) {
m := handlerTestManager() m := handlerTestManager()
defer m.Close() defer m.Close()
+85 -4
View File
@@ -11,6 +11,7 @@ import (
"tailscale.com/client/local" "tailscale.com/client/local"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg"
) )
const ( const (
@@ -22,6 +23,8 @@ const (
type tailscaleClient interface { type tailscaleClient interface {
WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error)
Status(ctx context.Context) (*ipnstate.Status, error) Status(ctx context.Context) (*ipnstate.Status, error)
GetPrefs(ctx context.Context) (*ipn.Prefs, error)
EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error)
} }
// ipnBusWatcher abstracts the IPN bus watcher for testing. // ipnBusWatcher abstracts the IPN bus watcher for testing.
@@ -43,6 +46,14 @@ func (w *localClientWrapper) Status(ctx context.Context) (*ipnstate.Status, erro
return w.client.Status(ctx) return w.client.Status(ctx)
} }
func (w *localClientWrapper) GetPrefs(ctx context.Context) (*ipn.Prefs, error) {
return w.client.GetPrefs(ctx)
}
func (w *localClientWrapper) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
return w.client.EditPrefs(ctx, mp)
}
// Manager manages Tailscale state via IPN bus events and subscriber notifications. // Manager manages Tailscale state via IPN bus events and subscriber notifications.
type Manager struct { type Manager struct {
state *TailscaleState state *TailscaleState
@@ -169,16 +180,36 @@ func (m *Manager) fetchAndBroadcast(ctx context.Context) {
statusCtx, cancel := context.WithTimeout(ctx, statusTimeout) statusCtx, cancel := context.WithTimeout(ctx, statusTimeout)
defer cancel() defer cancel()
status, err := m.client.Status(statusCtx) state, err := m.fetchState(statusCtx)
if err != nil { if err != nil {
log.Warnf("[Tailscale] Failed to fetch status: %v", err) log.Warnf("[Tailscale] Failed to fetch status: %v", err)
return return
} }
state := convertStatus(status)
m.updateState(state) m.updateState(state)
} }
// fetchState fetches the current status and merges in pref-derived fields
// (e.g. exit-node LAN access) that are not present in the IPN status itself.
func (m *Manager) fetchState(ctx context.Context) (*TailscaleState, error) {
status, err := m.client.Status(ctx)
if err != nil {
return nil, err
}
state := convertStatus(status)
// Prefs carry the exit-node LAN-access toggle, which the status does not
// expose. Treat a prefs failure as non-fatal so status still updates.
if prefs, err := m.client.GetPrefs(ctx); err != nil {
log.Warnf("[Tailscale] Failed to fetch prefs: %v", err)
} else if prefs != nil {
state.ExitNodeAllowLANAccess = prefs.ExitNodeAllowLANAccess
}
return state, nil
}
func (m *Manager) updateState(state *TailscaleState) { func (m *Manager) updateState(state *TailscaleState) {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state = state m.state = state
@@ -266,12 +297,62 @@ func (m *Manager) RefreshState() {
ctx, cancel := context.WithTimeout(m.ctx, statusTimeout) ctx, cancel := context.WithTimeout(m.ctx, statusTimeout)
defer cancel() defer cancel()
status, err := m.client.Status(ctx) state, err := m.fetchState(ctx)
if err != nil { if err != nil {
log.Warnf("[Tailscale] Failed to refresh state: %v", err) log.Warnf("[Tailscale] Failed to refresh state: %v", err)
return return
} }
state := convertStatus(status)
m.updateState(state) m.updateState(state)
} }
// Connect brings the Tailscale backend up (WantRunning = true).
func (m *Manager) Connect() error {
return m.editPrefs(&ipn.MaskedPrefs{
Prefs: ipn.Prefs{WantRunning: true},
WantRunningSet: true,
})
}
// Disconnect brings the Tailscale backend down (WantRunning = false).
func (m *Manager) Disconnect() error {
return m.editPrefs(&ipn.MaskedPrefs{
Prefs: ipn.Prefs{WantRunning: false},
WantRunningSet: true,
})
}
// SetExitNode selects the exit node identified by its stable node ID. An empty
// id clears the current exit node. Mirrors `tailscale set --exit-node=<id>`,
// which also clears any legacy IP-based exit node so a stale ExitNodeIP cannot
// silently take precedence over the now-empty ID.
func (m *Manager) SetExitNode(id string) error {
return m.editPrefs(&ipn.MaskedPrefs{
Prefs: ipn.Prefs{ExitNodeID: tailcfg.StableNodeID(id)},
ExitNodeIDSet: true,
ExitNodeIPSet: true,
})
}
// SetAllowLANAccess toggles whether locally accessible subnets remain
// reachable while an exit node is in use.
func (m *Manager) SetAllowLANAccess(enabled bool) error {
return m.editPrefs(&ipn.MaskedPrefs{
Prefs: ipn.Prefs{ExitNodeAllowLANAccess: enabled},
ExitNodeAllowLANAccessSet: true,
})
}
// editPrefs applies a masked prefs edit and refreshes state so subscribers see
// the result immediately, in addition to the IPN bus notification it triggers.
func (m *Manager) editPrefs(mp *ipn.MaskedPrefs) error {
ctx, cancel := context.WithTimeout(m.ctx, statusTimeout)
defer cancel()
if _, err := m.client.EditPrefs(ctx, mp); err != nil {
return err
}
m.RefreshState()
return nil
}
@@ -12,8 +12,16 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg"
) )
// blockingWatch is a watchFn that blocks until the context is cancelled, used
// by tests that exercise direct manager calls rather than the watch loop.
func blockingWatch(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error) {
<-ctx.Done()
return nil, ctx.Err()
}
// mockWatcher yields canned Notify events, then returns err or blocks until Close/context cancel. // mockWatcher yields canned Notify events, then returns err or blocks until Close/context cancel.
type mockWatcher struct { type mockWatcher struct {
events []ipn.Notify events []ipn.Notify
@@ -70,6 +78,8 @@ func (w *mockWatcher) Close() error {
type mockClient struct { type mockClient struct {
watchFn func(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error) watchFn func(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error)
statusFn func(ctx context.Context) (*ipnstate.Status, error) statusFn func(ctx context.Context) (*ipnstate.Status, error)
getPrefsFn func(ctx context.Context) (*ipn.Prefs, error)
editPrefsFn func(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error)
} }
func (c *mockClient) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error) { func (c *mockClient) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (ipnBusWatcher, error) {
@@ -80,6 +90,20 @@ func (c *mockClient) Status(ctx context.Context) (*ipnstate.Status, error) {
return c.statusFn(ctx) return c.statusFn(ctx)
} }
func (c *mockClient) GetPrefs(ctx context.Context) (*ipn.Prefs, error) {
if c.getPrefsFn != nil {
return c.getPrefsFn(ctx)
}
return &ipn.Prefs{}, nil
}
func (c *mockClient) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
if c.editPrefsFn != nil {
return c.editPrefsFn(ctx, mp)
}
return &ipn.Prefs{}, nil
}
func runningStatus() *ipnstate.Status { func runningStatus() *ipnstate.Status {
return &ipnstate.Status{ return &ipnstate.Status{
Version: "1.94.2", Version: "1.94.2",
@@ -296,3 +320,78 @@ func TestManager_RefreshState(t *testing.T) {
assert.True(t, state.Connected) assert.True(t, state.Connected)
assert.Equal(t, "cachyos", state.Self.Hostname) assert.Equal(t, "cachyos", state.Self.Hostname)
} }
func TestManager_RefreshState_MergesPrefs(t *testing.T) {
client := &mockClient{
watchFn: blockingWatch,
statusFn: func(ctx context.Context) (*ipnstate.Status, error) { return runningStatus(), nil },
getPrefsFn: func(ctx context.Context) (*ipn.Prefs, error) {
return &ipn.Prefs{ExitNodeAllowLANAccess: true}, nil
},
}
m := newManager(client)
defer m.Close()
m.RefreshState()
assert.True(t, m.GetState().ExitNodeAllowLANAccess)
}
func TestManager_Actions_EditPrefs(t *testing.T) {
var captured *ipn.MaskedPrefs
client := &mockClient{
watchFn: blockingWatch,
statusFn: func(ctx context.Context) (*ipnstate.Status, error) { return runningStatus(), nil },
editPrefsFn: func(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
captured = mp
return &ipn.Prefs{}, nil
},
}
m := newManager(client)
defer m.Close()
require.NoError(t, m.Connect())
require.NotNil(t, captured)
assert.True(t, captured.WantRunningSet)
assert.True(t, captured.WantRunning)
require.NoError(t, m.Disconnect())
assert.True(t, captured.WantRunningSet)
assert.False(t, captured.WantRunning)
require.NoError(t, m.SetExitNode("nABC123"))
assert.True(t, captured.ExitNodeIDSet)
assert.Equal(t, tailcfg.StableNodeID("nABC123"), captured.ExitNodeID)
// ExitNodeIPSet must also be set so a stale legacy ExitNodeIP cannot
// override the ID-based selection (mirrors `tailscale set --exit-node`).
assert.True(t, captured.ExitNodeIPSet)
require.NoError(t, m.SetExitNode(""))
assert.True(t, captured.ExitNodeIDSet)
assert.Equal(t, tailcfg.StableNodeID(""), captured.ExitNodeID)
// Clearing must zero both the ID and any legacy IP-based exit node.
assert.True(t, captured.ExitNodeIPSet)
require.NoError(t, m.SetAllowLANAccess(true))
assert.True(t, captured.ExitNodeAllowLANAccessSet)
assert.True(t, captured.ExitNodeAllowLANAccess)
}
func TestManager_Actions_PropagateError(t *testing.T) {
client := &mockClient{
watchFn: blockingWatch,
statusFn: func(ctx context.Context) (*ipnstate.Status, error) { return runningStatus(), nil },
editPrefsFn: func(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
return nil, fmt.Errorf("backend rejected edit")
},
}
m := newManager(client)
defer m.Close()
assert.Error(t, m.Connect())
assert.Error(t, m.SetExitNode("nABC123"))
assert.Error(t, m.SetAllowLANAccess(true))
}
+2
View File
@@ -7,6 +7,7 @@ type TailscaleState struct {
BackendState string `json:"backendState"` BackendState string `json:"backendState"`
MagicDNSSuffix string `json:"magicDnsSuffix"` MagicDNSSuffix string `json:"magicDnsSuffix"`
TailnetName string `json:"tailnetName"` TailnetName string `json:"tailnetName"`
ExitNodeAllowLANAccess bool `json:"exitNodeAllowLanAccess"`
Self Peer `json:"self"` Self Peer `json:"self"`
Peers []Peer `json:"peers"` Peers []Peer `json:"peers"`
} }
@@ -22,6 +23,7 @@ type Peer struct {
Online bool `json:"online"` Online bool `json:"online"`
LastSeen string `json:"lastSeen,omitempty"` LastSeen string `json:"lastSeen,omitempty"`
ExitNode bool `json:"exitNode"` ExitNode bool `json:"exitNode"`
ExitNodeOption bool `json:"exitNodeOption"`
Tags []string `json:"tags,omitempty"` Tags []string `json:"tags,omitempty"`
Owner string `json:"owner"` Owner string `json:"owner"`
Relay string `json:"relay,omitempty"` Relay string `json:"relay,omitempty"`
+2 -2
View File
@@ -201,7 +201,7 @@ func (m Model) viewInstallComplete() string {
wm := m.selectedWindowManager() wm := m.selectedWindowManager()
// mango launches DMS via `exec_once=dms run` (not a systemd session target) // mango launches DMS via `exec-once=dms run` (not a systemd session target)
loginHint := "If you do not have a greeter, login with \"niri-session\" or \"Hyprland\"" loginHint := "If you do not have a greeter, login with \"niri-session\" or \"Hyprland\""
switch wm { switch wm {
case deps.WindowManagerNiri: case deps.WindowManagerNiri:
@@ -223,7 +223,7 @@ func (m Model) viewInstallComplete() string {
b.WriteString(labelStyle.Render("Troubleshooting:") + "\n") b.WriteString(labelStyle.Render("Troubleshooting:") + "\n")
if wm == deps.WindowManagerMango { if wm == deps.WindowManagerMango {
b.WriteString(labelStyle.Render(" Disable autostart: ") + cmdStyle.Render("remove 'exec_once=dms run' from ~/.config/mango/config.conf") + "\n") b.WriteString(labelStyle.Render(" Disable autostart: ") + cmdStyle.Render("remove 'exec-once=dms run' from ~/.config/mango/config.conf") + "\n")
b.WriteString(labelStyle.Render(" View logs: ") + cmdStyle.Render("qs -p ~/.config/quickshell/dms log") + "\n") b.WriteString(labelStyle.Render(" View logs: ") + cmdStyle.Render("qs -p ~/.config/quickshell/dms log") + "\n")
} else { } else {
b.WriteString(labelStyle.Render(" Disable autostart: ") + cmdStyle.Render("systemctl --user disable dms") + "\n") b.WriteString(labelStyle.Render(" Disable autostart: ") + cmdStyle.Render("systemctl --user disable dms") + "\n")
+7 -7
View File
@@ -3,10 +3,10 @@
# Usage: ./create-source.sh <package-dir> [ubuntu-series] # Usage: ./create-source.sh <package-dir> [ubuntu-series]
# #
# Example: # Example:
# ./create-source.sh ../dms questing # Ubuntu 25.10 (default series in ppa-upload) # ./create-source.sh ../dms resolute # Ubuntu 26.04 LTS (default series in ppa-upload)
# ./create-source.sh ../dms resolute # Ubuntu 26.04 LTS # ./create-source.sh ../dms stonking # Ubuntu 26.10
# ./create-source.sh ../dms-git questing
# ./create-source.sh ../dms-git resolute # ./create-source.sh ../dms-git resolute
# ./create-source.sh ../dms-git stonking
set -e set -e
@@ -27,13 +27,13 @@ if [ $# -lt 1 ]; then
echo "Arguments:" echo "Arguments:"
echo " package-dir : Path to package directory (e.g., ../dms)" echo " package-dir : Path to package directory (e.g., ../dms)"
echo " ubuntu-series : Ubuntu series (optional, default: noble)" echo " ubuntu-series : Ubuntu series (optional, default: noble)"
echo " Options: noble, jammy, oracular, mantic, questing, resolute" echo " Options: noble, jammy, oracular, mantic, resolute, stonking"
echo echo
echo "Examples:" echo "Examples:"
echo " $0 ../dms questing"
echo " $0 ../dms resolute" echo " $0 ../dms resolute"
echo " $0 ../dms-git questing" echo " $0 ../dms stonking"
echo " $0 ../dms-git resolute" echo " $0 ../dms-git resolute"
echo " $0 ../dms-git stonking"
exit 1 exit 1
fi fi
@@ -135,7 +135,7 @@ check_ppa_version_exists() {
local CHECK_MODE="${4:-commit}" local CHECK_MODE="${4:-commit}"
local DISTRO_SERIES="${5:-}" local DISTRO_SERIES="${5:-}"
# Query Launchpad API (optionally scoped to one Ubuntu series so the same version can ship to questing and resolute) # Query Launchpad API (optionally scoped to one Ubuntu series so the same version can ship to resolute and stonking)
local API_URL="https://api.launchpad.net/1.0/~avengemedia/+archive/ubuntu/$PPA_NAME?ws.op=getPublishedSources&source_name=$SOURCE_NAME&status=Published" local API_URL="https://api.launchpad.net/1.0/~avengemedia/+archive/ubuntu/$PPA_NAME?ws.op=getPublishedSources&source_name=$SOURCE_NAME&status=Published"
if [[ -n "$DISTRO_SERIES" ]]; then if [[ -n "$DISTRO_SERIES" ]]; then
API_URL+="&distro_series=https://api.launchpad.net/1.0/ubuntu/${DISTRO_SERIES}" API_URL+="&distro_series=https://api.launchpad.net/1.0/ubuntu/${DISTRO_SERIES}"
+2 -2
View File
@@ -10,8 +10,8 @@
PPA_OWNER="avengemedia" PPA_OWNER="avengemedia"
LAUNCHPAD_API="https://api.launchpad.net/1.0" LAUNCHPAD_API="https://api.launchpad.net/1.0"
# Supported Ubuntu series for PPA builds (25.10 questing + 26.04 LTS resolute) # Supported Ubuntu series for PPA builds (26.04 LTS resolute + 26.10 stonking)
DISTRO_SERIES_LIST=(questing resolute) DISTRO_SERIES_LIST=(resolute stonking)
# Define packages (sync with ppa-upload.sh) # Define packages (sync with ppa-upload.sh)
ALL_PACKAGES=(dms dms-git dms-greeter) ALL_PACKAGES=(dms dms-git dms-greeter)
+3 -3
View File
@@ -5,7 +5,7 @@ set -euo pipefail
PPA_OWNER="avengemedia" PPA_OWNER="avengemedia"
LAUNCHPAD_API="https://api.launchpad.net/1.0" LAUNCHPAD_API="https://api.launchpad.net/1.0"
SERIES_LIST=(questing resolute) SERIES_LIST=(resolute stonking)
PACKAGE_FILTER="dms-git" PACKAGE_FILTER="dms-git"
REBUILD_RELEASE="" REBUILD_RELEASE=""
JSON=false JSON=false
@@ -72,12 +72,12 @@ embedded_commit() {
target_ppa() { target_ppa() {
local series="$1" local series="$1"
if [[ -n "$REBUILD_RELEASE" ]]; then if [[ -n "$REBUILD_RELEASE" ]]; then
if [[ "$series" == "resolute" ]]; then if [[ "$series" == "stonking" ]]; then
echo $((REBUILD_RELEASE + 1)) echo $((REBUILD_RELEASE + 1))
else else
echo "$REBUILD_RELEASE" echo "$REBUILD_RELEASE"
fi fi
elif [[ "$series" == "resolute" ]]; then elif [[ "$series" == "stonking" ]]; then
echo "2" echo "2"
else else
echo "1" echo "1"
+8 -8
View File
@@ -3,13 +3,13 @@
# Usage: ./ppa-upload.sh [package-name] [ppa-name] [ubuntu-series] [rebuild-number] [--keep-builds] [--rebuild=N] # Usage: ./ppa-upload.sh [package-name] [ppa-name] [ubuntu-series] [rebuild-number] [--keep-builds] [--rebuild=N]
# #
# Examples: # Examples:
# ./ppa-upload.sh dms # Upload to questing + resolute (default) # ./ppa-upload.sh dms # Upload to resolute + stonking (default)
# ./ppa-upload.sh dms 2 # Native: questing ppa2, resolute ppa3 (auto +1 on second series) # ./ppa-upload.sh dms 2 # Native: resolute ppa2, stonking ppa3 (auto +1 on second series)
# ./ppa-upload.sh dms --rebuild=2 # Rebuild with ppa2 (flag syntax) # ./ppa-upload.sh dms --rebuild=2 # Rebuild with ppa2 (flag syntax)
# ./ppa-upload.sh dms-git # Single package (both series) # ./ppa-upload.sh dms-git # Single package (both series)
# ./ppa-upload.sh all # All packages (each to both series) # ./ppa-upload.sh all # All packages (each to both series)
# ./ppa-upload.sh dms resolute # 26.04 LTS only (same as "dms dms resolute") # ./ppa-upload.sh dms resolute # 26.04 LTS only (same as "dms dms resolute")
# ./ppa-upload.sh dms questing # 25.10 only # ./ppa-upload.sh dms stonking # 26.10 only
# ./ppa-upload.sh dms dms resolute # Explicit PPA name + one series (optional form) # ./ppa-upload.sh dms dms resolute # Explicit PPA name + one series (optional form)
# ./ppa-upload.sh dms dms resolute 2 # One series + rebuild number # ./ppa-upload.sh dms dms resolute 2 # One series + rebuild number
# ./ppa-upload.sh distro/ubuntu/dms dms # Path-style (backward compatible) # ./ppa-upload.sh distro/ubuntu/dms dms # Path-style (backward compatible)
@@ -70,8 +70,8 @@ if [[ ${#POSITIONAL_ARGS[@]} -gt 0 ]]; then
fi fi
fi fi
# Shorthand: "dms resolute" / "dms questing" (package + series; PPA inferred — no need for "dms dms resolute") # Shorthand: "dms resolute" / "dms stonking" (package + series; PPA inferred — no need for "dms dms resolute")
if [[ ${#POSITIONAL_ARGS[@]} -eq 2 ]] && [[ "${POSITIONAL_ARGS[1]}" == "questing" || "${POSITIONAL_ARGS[1]}" == "resolute" ]]; then if [[ ${#POSITIONAL_ARGS[@]} -eq 2 ]] && [[ "${POSITIONAL_ARGS[1]}" == "resolute" || "${POSITIONAL_ARGS[1]}" == "stonking" ]]; then
PACKAGE_INPUT="${POSITIONAL_ARGS[0]}" PACKAGE_INPUT="${POSITIONAL_ARGS[0]}"
PPA_NAME_INPUT="" PPA_NAME_INPUT=""
UBUNTU_SERIES_RAW="${POSITIONAL_ARGS[1]}" UBUNTU_SERIES_RAW="${POSITIONAL_ARGS[1]}"
@@ -79,11 +79,11 @@ fi
SERIES_LIST=() SERIES_LIST=()
if [[ -z "$UBUNTU_SERIES_RAW" ]]; then if [[ -z "$UBUNTU_SERIES_RAW" ]]; then
SERIES_LIST=(questing resolute) SERIES_LIST=(resolute stonking)
elif [[ "$UBUNTU_SERIES_RAW" == "questing" || "$UBUNTU_SERIES_RAW" == "resolute" ]]; then elif [[ "$UBUNTU_SERIES_RAW" == "resolute" || "$UBUNTU_SERIES_RAW" == "stonking" ]]; then
SERIES_LIST=("$UBUNTU_SERIES_RAW") SERIES_LIST=("$UBUNTU_SERIES_RAW")
else else
error "Invalid Ubuntu series: $UBUNTU_SERIES_RAW (use questing, resolute, or omit for both)" error "Invalid Ubuntu series: $UBUNTU_SERIES_RAW (use resolute, stonking, or omit for both)"
exit 1 exit 1
fi fi
+9 -2
View File
@@ -40,10 +40,17 @@ override_dh_auto_install:
install -Dm644 DankMaterialShell-$(BASE_VERSION)/LICENSE \ install -Dm644 DankMaterialShell-$(BASE_VERSION)/LICENSE \
debian/dms-greeter/usr/share/doc/dms-greeter/LICENSE debian/dms-greeter/usr/share/doc/dms-greeter/LICENSE
# Install systemd tmpfiles/sysusers fragments only when present in the fetched source.
# sysusers-dms-greeter.conf landed upstream after v1.4.6; guarding both lets older
# release tarballs build, while future tags that ship the files install them automatically.
if [ -f DankMaterialShell-$(BASE_VERSION)/quickshell/systemd/tmpfiles-dms-greeter.conf ]; then \
install -Dpm0644 DankMaterialShell-$(BASE_VERSION)/quickshell/systemd/tmpfiles-dms-greeter.conf \ install -Dpm0644 DankMaterialShell-$(BASE_VERSION)/quickshell/systemd/tmpfiles-dms-greeter.conf \
debian/dms-greeter/usr/lib/tmpfiles.d/dms-greeter.conf debian/dms-greeter/usr/lib/tmpfiles.d/dms-greeter.conf; \
fi
if [ -f DankMaterialShell-$(BASE_VERSION)/quickshell/systemd/sysusers-dms-greeter.conf ]; then \
install -Dm644 DankMaterialShell-$(BASE_VERSION)/quickshell/systemd/sysusers-dms-greeter.conf \ install -Dm644 DankMaterialShell-$(BASE_VERSION)/quickshell/systemd/sysusers-dms-greeter.conf \
debian/dms-greeter/usr/lib/sysusers.d/dms-greeter.conf debian/dms-greeter/usr/lib/sysusers.d/dms-greeter.conf; \
fi
# Create cache directory structure (will be created by postinst) # Create cache directory structure (will be created by postinst)
mkdir -p debian/dms-greeter/var/cache/dms-greeter mkdir -p debian/dms-greeter/var/cache/dms-greeter
+90
View File
@@ -0,0 +1,90 @@
# Void Linux packaging
XBPS templates for DankMaterialShell on [Void Linux](https://voidlinux.org).
| Package | Source repo | Template |
| --- | --- | --- |
| `dms` | DankMaterialShell | [`srcpkgs/dms/template`](srcpkgs/dms/template) |
| `dms-greeter` (optional) | DankMaterialShell | [`srcpkgs/dms-greeter/template`](srcpkgs/dms-greeter/template) |
| `dgop` | AvengeMedia/dgop | maintained in the **danklinux** repo (`distro/void/srcpkgs/dgop`) |
| `danksearch` | AvengeMedia/danksearch | maintained in the **danklinux** repo (`distro/void/srcpkgs/danksearch`) |
All build from source.
## Distribution
These packages target the official
[`void-linux/void-packages`](https://github.com/void-linux/void-packages)
repository, so they install with a plain `xbps-install dms` and no extra setup.
Most dependencies (`quickshell`, `matugen`, `cava`, `niri`, `greetd`, …) are
already in Void; `dgop` and `danksearch` are packaged alongside in the
[danklinux repo](https://github.com/AvengeMedia/danklinux/tree/master/distro/void).
The templates here are the source of truth: copy each into a void-packages
checkout at `srcpkgs/<pkg>/template` to build or submit it. Only tagged releases
are packaged (no `-git`/nightly variant).
## Dependencies
Installing `dms` automatically pulls in `quickshell`, `accountsservice`, `dgop`,
and `matugen` (which drives the Material You theming). The rest are optional —
install whichever features you want:
| Package | Enables |
| --- | --- |
| `danksearch` | launcher / filesystem search |
| `cava` | audio visualiser widget |
| `qt6-multimedia` | system sound feedback |
| `qt6ct` | Qt app theming |
| `wtype` | virtual keyboard input |
| `power-profiles-daemon` | power profile control |
| `cups-pk-helper` | printer management |
| `NetworkManager` | network control |
| `i2c-tools` | external-monitor brightness (DDC) |
| `niri` / `hyprland` / `sway` | a Wayland compositor (niri is the team's choice) |
## Building & testing
Inside a `void-packages` checkout (symlink or copy these `srcpkgs/<pkg>` dirs in):
```sh
# build the dependency packages first (dms requires dgop)
./xbps-src pkg dgop
./xbps-src pkg danksearch
./xbps-src pkg dms
./xbps-src pkg dms-greeter # optional
# lint (xlint ships in the xtools package)
xlint srcpkgs/dms/template
# install the built packages
sudo xbps-install --repository=hostdir/binpkgs dms dgop
```
`dms` requires Go ≥ 1.26 in the build environment (per `core/go.mod`).
## Running the shell
DMS is a user-level Wayland shell with **no system service** — start it from your
compositor's autostart, e.g. niri:
```kdl
spawn-at-startup "dms" "run"
```
or Hyprland: `exec-once = dms run`.
## Greeter (optional)
Install `dms-greeter`, then let the CLI do the setup:
```sh
dms greeter enable # configures greetd + the Void seat/PAM bits below
dms greeter sync # optional: share theming with the shell
```
`dms greeter enable` handles what logind does automatically on systemd: it points
greetd at the greeter, enables `seatd`, adds `_greeter` to the `_seatd`/`video`/
`input` groups, and adds `pam_rundir` to `/etc/pam.d/greetd` (so the post-login
session gets an `XDG_RUNTIME_DIR`). A Wayland compositor and a working DRM device
(`/dev/dri/card*`) are required and not pulled in automatically.
@@ -0,0 +1,15 @@
dms-greeter installed.
Configure and enable it with:
dms greeter enable
This points greetd at the greeter and sets up everything Void needs that logind
would handle on systemd: enables seatd, adds the greeter user to the seat/video/
input groups, and adds pam_rundir to the greetd PAM stack. Optionally sync your
shell theme into the greeter with:
dms greeter sync
Requirements not pulled in automatically: a Wayland compositor (niri, hyprland,
sway, …) and a working DRM device (/dev/dri/card*; in a VM, enable virtio-gpu).
+35
View File
@@ -0,0 +1,35 @@
# Template file for 'dms-greeter'
#
# greetd greeter for DankMaterialShell
# Builds from the same DMS release tarball as 'dms'; keep version/checksum in sync.
# Setup is done by `dms greeter enable`, not by this package — see distro/void/README.md.
pkgname=dms-greeter
version=1.4.6
revision=1
short_desc="DankMaterialShell greeter for greetd"
maintainer="AvengeMedia <AvengeMedia.US@gmail.com>"
license="MIT"
homepage="https://danklinux.com"
distfiles="https://github.com/AvengeMedia/DankMaterialShell/archive/refs/tags/v${version}.tar.gz"
checksum=f54601e522c883fa9cce02bec070e4321e47389a1cf453e7ad0bb7379ad91b61
depends="greetd quickshell acl-progs seatd pam_rundir"
# Cache dir the greeter uses as $HOME (owned by greetd's _greeter user).
make_dirs="/var/cache/dms-greeter 0750 _greeter _greeter"
do_install() {
# Launcher wrapper -> /usr/bin/dms-greeter
vbin quickshell/Modules/Greetd/assets/dms-greeter
# Same QML tree as the shell; greeter mode is selected at runtime via DMS_RUN_GREETER.
vmkdir usr/share/quickshell/dms-greeter
vcopy "quickshell/*" usr/share/quickshell/dms-greeter
# Sample compositor configs for reference
vinstall quickshell/Modules/Greetd/assets/dms-niri.kdl 644 usr/share/dms-greeter
vinstall quickshell/Modules/Greetd/assets/dms-hypr.conf 644 usr/share/dms-greeter
vdoc quickshell/Modules/Greetd/README.md
vlicense LICENSE
}
+48
View File
@@ -0,0 +1,48 @@
# Template file for 'dms'
#
# DankMaterialShell stable release
#
# NOTE: the binary is built with the `distro_binary` build tag, which is the
# packaged variant upstream ships (it drops the in-app self-update command).
pkgname=dms
version=1.4.6
revision=1
build_style=go
build_wrksrc="core"
go_import_path="github.com/AvengeMedia/DankMaterialShell/core"
go_package="${go_import_path}/cmd/dms"
go_build_tags="distro_binary"
go_ldflags="-X main.Version=${version}"
short_desc="DankMaterialShell — Material 3 desktop shell for Wayland"
maintainer="AvengeMedia <AvengeMedia.US@gmail.com>"
license="MIT"
homepage="https://danklinux.com"
changelog="https://github.com/AvengeMedia/DankMaterialShell/releases"
distfiles="https://github.com/AvengeMedia/DankMaterialShell/archive/refs/tags/v${version}.tar.gz"
checksum=f54601e522c883fa9cce02bec070e4321e47389a1cf453e7ad0bb7379ad91b61
# Optional feature deps (XBPS has no "recommends") are listed in distro/void/README.md.
depends="quickshell accountsservice dgop matugen"
post_install() {
# QML shell tree (build_style=go already installed the dms binary)
vmkdir usr/share/quickshell/dms
vcopy "${wrksrc}/quickshell/*" usr/share/quickshell/dms
echo "${version}" > "${DESTDIR}/usr/share/quickshell/dms/VERSION"
# Desktop entry + icon
vinstall "${wrksrc}/assets/dms-open.desktop" 644 usr/share/applications
vinstall "${wrksrc}/assets/danklogo.svg" 644 usr/share/icons/hicolor/scalable/apps
# Shell completions (generated by the built binary; skip when cross-building)
vmkdir usr/share/bash-completion/completions
vmkdir usr/share/zsh/site-functions
vmkdir usr/share/fish/vendor_completions.d
if [ -z "$CROSS_BUILD" ]; then
"${DESTDIR}/usr/bin/dms" completion bash > "${DESTDIR}/usr/share/bash-completion/completions/dms"
"${DESTDIR}/usr/bin/dms" completion zsh > "${DESTDIR}/usr/share/zsh/site-functions/_dms"
"${DESTDIR}/usr/bin/dms" completion fish > "${DESTDIR}/usr/share/fish/vendor_completions.d/dms.fish"
fi
vlicense "${wrksrc}/LICENSE"
}
+21 -1
View File
@@ -6,6 +6,18 @@ DankMaterialShell provides comprehensive IPC (Inter-Process Communication) funct
dms ipc call <target> <function> [parameters...] dms ipc call <target> <function> [parameters...]
``` ```
## Discovering IPC commands
List all available targets and functions while DMS is running:
```bash
dms ipc list
dms ipc # same
dms ipc --help # same, plus usage text
```
Live listing requires DMS to be running. If listing fails, use this document or the [Keybinds & IPC docs](https://danklinux.com/docs/dankmaterialshell/keybinds-ipc) as an offline reference.
## Target: `audio` ## Target: `audio`
Audio system control and information. Audio system control and information.
@@ -707,7 +719,7 @@ File browser controls for selecting wallpapers and profile images.
- Both browsers support common image formats (jpg, jpeg, png, bmp, gif, webp) - Both browsers support common image formats (jpg, jpeg, png, bmp, gif, webp)
### Target: `color-picker` ### Target: `color-picker`
Color picker modal control. In-shell color picker modal for theme and settings color selection.
**Functions:** **Functions:**
- `open` - Show color picker modal - `open` - Show color picker modal
@@ -718,6 +730,14 @@ Color picker modal control.
- `toggle` - Toggle color picker modal visibility - `toggle` - Toggle color picker modal visibility
- `toggleInstant` - Toggle color picker modal visibility without animation on hide - `toggleInstant` - Toggle color picker modal visibility without animation on hide
**Note:** This controls the in-shell modal. To pick a pixel from the screen via CLI, use `dms color pick` instead (see [Color Picker CLI](https://danklinux.com/docs/dankmaterialshell/cli-color-picker)).
**Examples:**
```bash
dms ipc call color-picker toggle
dms ipc call color-picker openColor "#3f51b5"
```
### Target: `hypr` ### Target: `hypr`
Hyprland-specific controls including keybinds cheatsheet and workspace overview (Hyprland only). Hyprland-specific controls including keybinds cheatsheet and workspace overview (Hyprland only).

Some files were not shown because too many files have changed in this diff Show More