Skip to content

feat(application): cross-platform system sleep/wake events#5423

Closed
leaanthony wants to merge 3 commits into
masterfrom
power-events
Closed

feat(application): cross-platform system sleep/wake events#5423
leaanthony wants to merge 3 commits into
masterfrom
power-events

Conversation

@leaanthony

@leaanthony leaanthony commented May 13, 2026

Copy link
Copy Markdown
Member

Summary

Adds cross-platform sleep/wake events so apps can react to the system suspending/resuming. Closes a long-standing gap: Windows already exposed WM_POWERBROADCAST as Windows.APMSuspend / APMResumeAutomatic / APMResumeSuspend, but macOS and Linux had no equivalent.

Three layered additions:

  1. macOS — observes NSWorkspace's notification centre (not the default one, which is what NSApplicationDelegate uses) and emits four new events:

    • Mac.ApplicationWillSleepNSWorkspaceWillSleepNotification
    • Mac.ApplicationDidWakeNSWorkspaceDidWakeNotification
    • Mac.ApplicationScreensDidSleepNSWorkspaceScreensDidSleepNotification
    • Mac.ApplicationScreensDidWakeNSWorkspaceScreensDidWakeNotification

    Wired in application_darwin.go::init() alongside the existing theme-change observer. Events declared with the ! suffix in events.txt so the generator skips its auto-selector emission — NSWorkspace selectors don't belong on NSApplicationDelegate.

  2. Linux — subscribes to org.freedesktop.login1.Manager.PrepareForSleep on the system bus. The signal fires twice with a boolean arg (true before suspend, false on resume), dispatched to Linux.SystemWillSleep and Linux.SystemDidWake. Mirrors monitorThemeChanges() in shape. Logs a warning + exits gracefully on systems without logind/elogind (Alpine, Void, some Devuan setups) so the rest of the app keeps running.

  3. Common forwarding — two new common events:

    • Common.SystemWillSleep
    • Common.SystemDidWake

    Each platform's events_common_<os>.go map gains an entry that forwards the platform-specific event into the common one (same pattern as Common.ThemeChanged and Common.ApplicationStarted):

    Source → Common
    Mac.ApplicationWillSleep Common.SystemWillSleep
    Mac.ApplicationDidWake Common.SystemDidWake
    Windows.APMSuspend Common.SystemWillSleep
    Windows.APMResumeAutomatic Common.SystemDidWake
    Linux.SystemWillSleep Common.SystemWillSleep
    Linux.SystemDidWake Common.SystemDidWake

    Apps can now subscribe once, cross-platform:

    app.OnApplicationEvent(events.Common.SystemDidWake, func(*application.ApplicationEvent) {
        // fires on macOS, Windows, and Linux
    })

Design notes

  • Windows.APMResumeSuspend deliberately NOT mapped to Common.SystemDidWake. It fires after APMResumeAutomatic when the resume was triggered by user input, so mapping both would double-fire the common event for keyboard/mouse wakes.
  • Mac.ApplicationScreensDidSleep/Wake kept platform-specific. They fire on display-power transitions (e.g. lid lowered, display dimmed) distinct from full system sleep. No clean Windows/Linux equivalent — display power lives in DE-specific D-Bus interfaces (GNOME ScreenSaver, KDE PowerManagement) which are too fragmented to unify cleanly.
  • The Linux subscription uses the system bus, not the session bus that monitorThemeChanges uses — logind is a system-level service.

Test plan

  • darwin: go build, go vet, go test ./pkg/events/ ./pkg/application/ — all pass
  • linux (lin-node1, Ubuntu, GTK4/3 + WebKit2GTK-4.1): go build, go test ./pkg/application/ — all pass
  • windows: GOOS=windows go vet ./pkg/events/ clean (CGO build path can't run here, but events_common_windows.go is straight Go, mirroring the existing pattern)
  • manual sleep test on macOS — observe Common.SystemDidWake fire after pmset sleepnow + wake
  • manual sleep test on Linux — observe Common.SystemDidWake fire after systemctl suspend + wake
  • manual sleep test on Windows — observe Common.SystemDidWake fire after standby + wake

Automated tests don't cover any of the existing AppDelegate-selector or D-Bus paths either; the manual sleep test mirrors how the existing theme-change and Windows APM events are validated.

Summary by CodeRabbit

  • New Features
    • System sleep and wake events are now available across all supported platforms (macOS, Linux, and Windows)
    • Screen sleep and wake event notifications have been added for macOS
    • Extended event detection capabilities for system power lifecycle changes
    • Enhanced event routing to include system power state transitions across all platforms

Review Change Stack

Copilot AI review requested due to automatic review settings May 13, 2026 08:18
@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3e17df51-1d31-439a-8ccd-5ba5b5887b46

📥 Commits

Reviewing files that changed from the base of the PR and between a72d10e and bed7ef2.

📒 Files selected for processing (14)
  • v3/internal/generator/collect/known_events.go
  • v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts
  • v3/pkg/application/application_darwin.go
  • v3/pkg/application/application_darwin_delegate.m
  • v3/pkg/application/application_linux.go
  • v3/pkg/application/events_common_darwin.go
  • v3/pkg/application/events_common_linux.go
  • v3/pkg/application/events_common_windows.go
  • v3/pkg/events/events.go
  • v3/pkg/events/events.txt
  • v3/pkg/events/events_darwin.h
  • v3/pkg/events/events_ios.h
  • v3/pkg/events/events_linux.h
  • v3/pkg/events/known_events.go

Walkthrough

This PR extends the Wails application event system with cross-platform system sleep and wake notifications. It defines new event types for Common, Linux, and macOS platforms, implements platform-specific signal handlers using NSWorkspace on macOS and DBus systemd-logind on Linux, and maps all platform-specific events to unified common event types.

Changes

System Sleep/Wake Events

Layer / File(s) Summary
Event type definition and ID allocation
v3/pkg/events/events.txt, v3/pkg/events/events.go, v3/pkg/events/events_darwin.h, v3/pkg/events/events_ios.h, v3/pkg/events/events_linux.h
Adds SystemDidWake and SystemWillSleep to common and platform-specific event enums; allocates numeric IDs within existing sequences, causing all subsequent event IDs across Common, Linux, macOS, Windows, and iOS to renumber. Updates C header constants and MAX_EVENTS bounds to match.
Event registry and runtime codegen
v3/internal/generator/collect/known_events.go, v3/pkg/events/known_events.go, v3/pkg/events/events.go, v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts
Extends Go event registries to recognize new platform sleep/wake event name strings; expands eventToJS lookup to map new and renumbered event IDs to "platform:eventName" strings; generates TypeScript event type constants for Mac, Linux, and Common events.
macOS sleep/wake notification handling
v3/pkg/application/application_darwin.go, v3/pkg/application/application_darwin_delegate.m
Registers NSWorkspace notification observers for workspaceWillSleep, workspaceDidWake, workspaceScreensDidSleep, and workspaceScreensDidWake; implements four AppDelegate handler methods that emit corresponding application events when listeners exist.
Linux systemd-logind signal monitoring
v3/pkg/application/application_linux.go
Adds monitorPowerEvents() goroutine that connects to system DBus, subscribes to systemd-logind PrepareForSleep signals, and emits SystemWillSleep or SystemDidWake based on signal payload; initializes monitoring during app startup with graceful failure handling.
Platform to common event mapping
v3/pkg/application/events_common_darwin.go, v3/pkg/application/events_common_linux.go, v3/pkg/application/events_common_windows.go
Extends platform-to-common event translation maps on macOS (ApplicationWillSleep/ApplicationDidWake → SystemWillSleep/SystemDidWake), Linux (SystemWillSleep/SystemDidWake → SystemWillSleep/SystemDidWake), and Windows (APMSuspend/APMResumeAutomatic → SystemWillSleep/SystemDidWake).

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

MacOS, Windows, runtime, v3-alpha, size:XXL, lgtm

Poem

🐰 Hoppy times with power events,
Sleep and wake across all tents,
Mac and Linux now align,
Common ground, a system's sign!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding cross-platform system sleep/wake event support, which aligns with the primary changeset objective.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the feature summary, design decisions, and test plan with clear motivation for the changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch power-events

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@v3/internal/term/term.go`:
- Around line 105-110: The Error function currently returns early when
outputEnabled is false, which can suppress fatal error reporting; update the
Error implementation (function Error) to always emit the error output regardless
of the outputEnabled flag (i.e., remove or bypass the `if !outputEnabled {
return }` guard) so that calls like term.Error(err) always print the error
indicator and message; keep the existing formatting (col(ansiRed, "✗") and
sprint(input)) but do not gate it on outputEnabled.
- Around line 206-222: The HeaderTable rendering can panic when rows are ragged
because widths for extra columns default to 0, causing strings.Repeat to get a
negative count; in the HeaderTable logic (the loops that build widths and then
compose lines using widths and padded := cell + strings.Repeat(" ",
w-len(cell))), ensure the pad count is never negative by computing w safely
(e.g., when j >= len(widths) treat w as len(cell) or use max(widths[j],
len(cell))) or clamp pad := max(0, w-len(cell)) before calling strings.Repeat;
update the code paths that set w and build padded strings in the
HeaderTable/term table rendering to avoid negative repeat counts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7742c1a9-75ea-40a0-ac86-61ff0841f6a3

📥 Commits

Reviewing files that changed from the base of the PR and between 6944537 and a72d10e.

📒 Files selected for processing (28)
  • v3/cmd/wails3/main.go
  • v3/go.mod
  • v3/internal/commands/appimage.go
  • v3/internal/commands/capabilities.go
  • v3/internal/commands/entitlements_setup.go
  • v3/internal/commands/init.go
  • v3/internal/commands/sign.go
  • v3/internal/commands/signing_setup.go
  • v3/internal/commands/update_cli.go
  • v3/internal/doctor/doctor.go
  • v3/internal/generator/analyse_test.go
  • v3/internal/generator/collect/known_events.go
  • v3/internal/generator/config/log.go
  • v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts
  • v3/internal/templates/templates.go
  • v3/internal/term/term.go
  • v3/pkg/application/application_darwin.go
  • v3/pkg/application/application_darwin_delegate.m
  • v3/pkg/application/application_linux.go
  • v3/pkg/application/events_common_darwin.go
  • v3/pkg/application/events_common_linux.go
  • v3/pkg/application/events_common_windows.go
  • v3/pkg/events/events.go
  • v3/pkg/events/events.txt
  • v3/pkg/events/events_darwin.h
  • v3/pkg/events/events_ios.h
  • v3/pkg/events/events_linux.h
  • v3/pkg/events/known_events.go

Comment thread v3/internal/term/term.go Outdated
Comment on lines 105 to 110
func Error(input any) {
if !outputEnabled {
return
}
fmt.Println(" " + col(ansiRed, "✗") + " " + sprint(input))
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not gate fatal error output behind outputEnabled.

At Line 106, Error() returns early when output is disabled. Since main() now reports command failures via term.Error(err), quiet mode can hide fatal errors entirely.

Proposed fix
 func Error(input any) {
-	if !outputEnabled {
-		return
-	}
-	fmt.Println("  " + col(ansiRed, "✗") + "  " + sprint(input))
+	fmt.Fprintln(os.Stderr, "  "+col(ansiRed, "✗")+"  "+sprint(input))
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func Error(input any) {
if !outputEnabled {
return
}
fmt.Println(" " + col(ansiRed, "✗") + " " + sprint(input))
}
func Error(input any) {
fmt.Fprintln(os.Stderr, " "+col(ansiRed, "✗")+" "+sprint(input))
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@v3/internal/term/term.go` around lines 105 - 110, The Error function
currently returns early when outputEnabled is false, which can suppress fatal
error reporting; update the Error implementation (function Error) to always emit
the error output regardless of the outputEnabled flag (i.e., remove or bypass
the `if !outputEnabled { return }` guard) so that calls like term.Error(err)
always print the error indicator and message; keep the existing formatting
(col(ansiRed, "✗") and sprint(input)) but do not gate it on outputEnabled.

Comment thread v3/internal/term/term.go Outdated
Comment on lines +206 to +222
widths := make([]int, len(rows[0]))
for _, row := range rows {
for i, cell := range row {
if i < len(widths) && len(cell) > widths[i] {
widths[i] = len(cell)
}
}
}
for i, row := range rows {
line := " "
for j, cell := range row {
w := 0
if j < len(widths) {
w = widths[j]
}
padded := cell + strings.Repeat(" ", w-len(cell))
if i == 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

HeaderTable can panic on ragged rows with extra columns.

At Line 221, strings.Repeat(" ", w-len(cell)) can receive a negative count when a data row has more columns than the header row (w defaults to 0 for out-of-range columns).

Proposed fix
 func HeaderTable(rows [][]string) {
 	if !outputEnabled || len(rows) == 0 {
 		return
 	}
-	widths := make([]int, len(rows[0]))
+	maxCols := 0
+	for _, row := range rows {
+		if len(row) > maxCols {
+			maxCols = len(row)
+		}
+	}
+	widths := make([]int, maxCols)
 	for _, row := range rows {
 		for i, cell := range row {
 			if i < len(widths) && len(cell) > widths[i] {
 				widths[i] = len(cell)
 			}
 		}
 	}
 	for i, row := range rows {
 		line := "  "
 		for j, cell := range row {
 			w := 0
 			if j < len(widths) {
 				w = widths[j]
 			}
-			padded := cell + strings.Repeat(" ", w-len(cell))
+			pad := w - len(cell)
+			if pad < 0 {
+				pad = 0
+			}
+			padded := cell + strings.Repeat(" ", pad)
 			if i == 0 {
 				line += col(ansiBold, padded) + "  "
 			} else {
 				line += padded + "  "
 			}
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@v3/internal/term/term.go` around lines 206 - 222, The HeaderTable rendering
can panic when rows are ragged because widths for extra columns default to 0,
causing strings.Repeat to get a negative count; in the HeaderTable logic (the
loops that build widths and then compose lines using widths and padded := cell +
strings.Repeat(" ", w-len(cell))), ensure the pad count is never negative by
computing w safely (e.g., when j >= len(widths) treat w as len(cell) or use
max(widths[j], len(cell))) or clamp pad := max(0, w-len(cell)) before calling
strings.Repeat; update the code paths that set w and build padded strings in the
HeaderTable/term table rendering to avoid negative repeat counts.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds cross-platform system sleep/wake lifecycle events to the v3 application event system (macOS + Linux parity with existing Windows power events), and forwards them into two new common events so apps can subscribe once across OSes. It also includes a broad CLI terminal-output refactor replacing pterm with a new internal/term package (ANSI + glyph spinner), updating multiple commands accordingly.

Changes:

  • Add new platform events for macOS (NSWorkspace sleep/wake + screen sleep/wake) and Linux (logind PrepareForSleep), plus new common events Common.SystemWillSleep / Common.SystemDidWake.
  • Forward platform-specific power events into the new common events on macOS/Linux/Windows.
  • Replace CLI output/spinner plumbing (pterm) with internal/term and update multiple CLI commands + dependencies.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
v3/pkg/events/known_events.go Registers new common/linux/mac sleep/wake event names as “known events”.
v3/pkg/events/events.txt Declares new sleep/wake events for generator input (including “!” ignored-selector markers).
v3/pkg/events/events.go Adds new events.Common + platform event constants; updates numeric IDs and JS name mapping.
v3/pkg/events/events_linux.h Updates Linux C header event IDs + MAX_EVENTS for newly inserted events.
v3/pkg/events/events_ios.h Renumbers iOS C header event IDs due to earlier insertions in the global event list.
v3/pkg/events/events_darwin.h Updates macOS C header event IDs + adds new workspace sleep/wake event IDs.
v3/pkg/application/events_common_windows.go Forwards Windows APM suspend/resume into new common sleep/wake events.
v3/pkg/application/events_common_linux.go Forwards Linux sleep/wake into common sleep/wake events.
v3/pkg/application/events_common_darwin.go Forwards macOS workspace sleep/wake into common sleep/wake events.
v3/pkg/application/application_linux.go Subscribes to logind PrepareForSleep on system bus and emits Linux sleep/wake events.
v3/pkg/application/application_darwin.go Observes NSWorkspace notification center to receive sleep/wake notifications.
v3/pkg/application/application_darwin_delegate.m Implements NSWorkspace notification selectors and emits corresponding application events.
v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts Exposes new event type strings for Common/Linux/Mac in the runtime TS constants.
v3/internal/generator/collect/known_events.go Keeps generator-side known-event list in sync with new sleep/wake events.
v3/internal/generator/config/log.go Removes the pterm-based default logger implementation from generator config.
v3/internal/generator/analyse_test.go Updates test logging to term.Warning (but still references removed logger helper).
v3/internal/term/term.go Introduces new ANSI + glyph terminal UI, spinner, and logger adapter.
v3/internal/templates/templates.go Switches init template UI output from pterm table/confirm to term helpers.
v3/internal/doctor/doctor.go Switches doctor output + spinner from pterm to term helpers and tables.
v3/internal/commands/update_cli.go Switches update output to term + spinner and adjusts messaging/formatting.
v3/internal/commands/signing_setup.go Switches signing setup CLI output from pterm to term.
v3/internal/commands/sign.go Switches sign command output from pterm to term.
v3/internal/commands/init.go Switches init template listing output to term table helper.
v3/internal/commands/entitlements_setup.go Switches entitlements setup output from pterm to term.
v3/internal/commands/capabilities.go Prints JSON via fmt.Println instead of pterm.
v3/internal/commands/appimage.go Replaces pterm progress output with term spinner/info output.
v3/cmd/wails3/main.go Switches top-level CLI error/footer output to term/fmt and adds new footer formatting.
v3/go.mod Removes pterm, adds glyph, updates Go version directive and indirect deps.
Comments suppressed due to low confidence (1)

v3/internal/generator/analyse_test.go:115

  • config.DefaultPtermLogger was removed from internal/generator/config/log.go, but this test still calls it. This will fail to compile. Use config.NullLogger (or another test logger) when calling FindServices instead of the deleted helper.
			}

			got := make([]string, 0)

			services, registerService, err := FindServices(pkgs, systemPaths, config.DefaultPtermLogger(nil))

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread v3/internal/commands/init.go Outdated
Comment on lines +222 to +224
fmt.Println()
term.HeaderTable(rows)
fmt.Println()
Comment on lines 60 to 64
info, err := operatingsystem.Info()
if err != nil {
term.StopSpinner(spinner)
term.Error("Failed to get system information")
return err
Comment thread v3/internal/term/term.go Outdated
Comment on lines +309 to +317
msg := text
frame := 0

// ANSI escape code to reset text formatting
resetFormat := "\x1b[0m"
app := glyph.NewInlineApp()
app.Height(1)
app.SetView(
glyph.HBox(
glyph.SpaceW(2),
glyph.Spinner(&frame).Frames(glyph.SpinnerBraille).FG(glyph.Cyan),
Comment thread v3/cmd/wails3/main.go Outdated
Comment on lines +148 to +155
func printFooter() {
if !commands.DisableFooter {
docsLink := term.Hyperlink("https://v3.wails.io/getting-started/your-first-app/", "wails3 docs")

pterm.Println(pterm.LightGreen("\nNeed documentation? Run: ") + pterm.LightBlue(docsLink))
// Check if we're in a teminal
printer := pterm.PrefixPrinter{
MessageStyle: pterm.NewStyle(pterm.FgLightGreen),
Prefix: pterm.Prefix{
Style: pterm.NewStyle(pterm.FgRed, pterm.BgLightWhite),
Text: "♥ ",
},
}

linkText := term.Hyperlink("https://github.com/sponsors/leaanthony", "wails3 sponsor")
printer.Println("If Wails is useful to you or your company, please consider sponsoring the project: " + pterm.LightBlue(linkText))
docsLink := term.Hyperlink("https://v3.wails.io/getting-started/your-first-app/", "docs")
sponsorLink := term.Hyperlink("https://github.com/sponsors/leaanthony", "github.com/sponsors/leaanthony")
fmt.Println()
fmt.Println(" " + term.Dim("docs")+" "+docsLink)
fmt.Println(" " + term.Red("♥") + " " + sponsorLink)
fmt.Println()
Comment thread v3/internal/templates/templates.go Outdated
func confirmRemote(_ *Template) bool {
term.Warning("Remote template — the Wails project takes no responsibility for 3rd party templates.")
term.Warning("Only use remote templates that you trust.")
fmt.Println()
Mirrors the windows:APMSuspend / APMResumeAutomatic / APMResumeSuspend
events that Wails v3 already raises from WM_POWERBROADCAST on Windows.

NSWorkspace power notifications post to its own notification center
(not the default NSNotificationCenter that NSApplicationDelegate uses)
so the events are declared with the `!` suffix in events.txt to skip
the delegate-selector auto-generation, and observers are wired by hand
in application_darwin.go's init() alongside the existing theme-change
observer on NSDistributedNotificationCenter.

New events:
- mac:ApplicationWillSleep         (NSWorkspaceWillSleepNotification)
- mac:ApplicationDidWake           (NSWorkspaceDidWakeNotification)
- mac:ApplicationScreensDidSleep   (NSWorkspaceScreensDidSleepNotification)
- mac:ApplicationScreensDidWake    (NSWorkspaceScreensDidWakeNotification)

Verification: compile + vet + existing unit tests pass on macOS, linux,
windows. Runtime firing of the observers is not exercised by automated
tests (same gap as the rest of the AppDelegate selectors) — to be
confirmed via xbar2's #807 follow-up wiring and a manual sleep test.

Motivation: xbar2 needs DidWake to force a plugin refresh sweep after
sleep, addressing upstream xbar issue #807 (the most-upvoted open bug).
Adds Linux equivalents to the mac:ApplicationDidWake / WillSleep events
introduced in the previous commit, completing power-event coverage
across macOS, Windows, and Linux.

Implementation subscribes to org.freedesktop.login1.Manager's
PrepareForSleep signal on the system bus. The signal fires twice with
a boolean arg — true just before suspend (→ linux:SystemWillSleep),
false on resume (→ linux:SystemDidWake). The pattern mirrors
monitorThemeChanges() in the same file (goroutine + AddMatchSignal +
range over Signal channel), differing only in bus (system vs session)
and dispatch logic.

Graceful degradation: distros without logind/elogind reachable on the
system bus (Alpine, Void, some Devuan setups) log a warning and the
goroutine exits — the rest of the application keeps running. This
matches the existing theme-monitor behaviour for missing session bus.

New events:
- linux:SystemWillSleep   (PrepareForSleep arg=true)
- linux:SystemDidWake     (PrepareForSleep arg=false)

Verification: darwin build + vet + tests pass. Linux cross-compile
requires a GTK toolchain not available in this environment, so runtime
behaviour will be confirmed when the branch is built on Linux + a
manual systemctl suspend test. The function structure is a near-copy
of the existing monitorThemeChanges() so the parse-time risk is low.
godbus API calls (ConnectSystemBus, WithMatchInterface, WithMatchMember,
WithMatchObjectPath) verified against v5.2.2 (the version in go.mod).
Adds two cross-platform power events so apps can listen for sleep/wake
once instead of branching on OS:

    app.OnApplicationEvent(events.Common.SystemDidWake, …)

Each platform's events_common_<os>.go map gains an entry that
forwards the platform-specific event into the common one (same
pattern as Common.ThemeChanged and Common.ApplicationStarted):

  darwin:  Mac.ApplicationWillSleep    → Common.SystemWillSleep
           Mac.ApplicationDidWake      → Common.SystemDidWake
  windows: Windows.APMSuspend          → Common.SystemWillSleep
           Windows.APMResumeAutomatic  → Common.SystemDidWake
  linux:   Linux.SystemWillSleep       → Common.SystemWillSleep
           Linux.SystemDidWake         → Common.SystemDidWake

Notes:
- Windows APMResumeSuspend is deliberately not mapped — it fires
  *after* APMResumeAutomatic when the wake was triggered by user
  input, so mapping both would double-fire Common.SystemDidWake.
- Mac.ApplicationScreensDidWake / ScreensDidSleep are kept platform-
  specific; they fire on display power state (separate from system
  sleep) and have no Linux/Windows equivalent.

Verified: darwin build + tests pass locally; Linux build + tests
pass on lin-node1; windows cross-vet of pkg/events clean.
@leaanthony

Copy link
Copy Markdown
Member Author

Rebased onto current master and force-pushed. The original branch was based on a stale sandbox snapshot that pulled in an unrelated pterm → custom-term migration, which is what CodeRabbit's v3/internal/term/term.go comments were flagging. Those changes are gone from this PR (head is now bed7ef2).

The PR diff is now 14 files / +787 / −632, all on-topic for the sleep/wake event work. The events.go size remains large because adding events renumbers IDs across all platforms — that's a generator artifact, not new code.

CodeRabbit can take another pass.

@leaanthony

Copy link
Copy Markdown
Member Author

Superseded by #5425 — fresh PR on a branch cleanly rebased onto current master, with documentation added. Closing this thread to avoid review confusion from the earlier sandbox-drift state.

@leaanthony leaanthony closed this May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants