summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput
diff options
context:
space:
mode:
authorNippy <nippy@rp1.hu>2026-05-09 13:33:09 +0200
committerNippy <nippy@rp1.hu>2026-05-09 13:33:09 +0200
commita2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5 (patch)
tree1a8769217f84bfe9d6216fafaadaf8cdd876d457 /raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput
parent34b9c34f982b2596cfa9e368a2d7f74e9a17477c (diff)
downloadRaveOS-PKGBUILD-a2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5.tar.gz
RaveOS-PKGBUILD-a2b924d7e9492b978ad6dc33b6c1ffcb304b4bc5.zip
raveos update
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/handlers.go282
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager.go492
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager_test.go414
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/types.go192
4 files changed, 0 insertions, 1380 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/handlers.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/handlers.go
deleted file mode 100644
index c885e13..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/handlers.go
+++ /dev/null
@@ -1,282 +0,0 @@
-package wlroutput
-
-import (
- "encoding/json"
- "fmt"
- "net"
- "time"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/log"
- "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/wlr_output_management"
- "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
-)
-
-type HeadConfig struct {
- Name string `json:"name"`
- Enabled bool `json:"enabled"`
- ModeID *uint32 `json:"modeId,omitempty"`
- CustomMode *struct {
- Width int32 `json:"width"`
- Height int32 `json:"height"`
- Refresh int32 `json:"refresh"`
- } `json:"customMode,omitempty"`
- Position *struct{ X, Y int32 } `json:"position,omitempty"`
- Transform *int32 `json:"transform,omitempty"`
- Scale *float64 `json:"scale,omitempty"`
- AdaptiveSync *uint32 `json:"adaptiveSync,omitempty"`
-}
-
-type ConfigurationRequest struct {
- Heads []HeadConfig `json:"heads"`
- Test bool `json:"test"`
-}
-
-func HandleRequest(conn net.Conn, req models.Request, manager *Manager) {
- if manager == nil {
- models.RespondError(conn, req.ID, "wlroutput manager not initialized")
- return
- }
-
- switch req.Method {
- case "wlroutput.getState":
- handleGetState(conn, req, manager)
- case "wlroutput.applyConfiguration":
- handleApplyConfiguration(conn, req, manager, false)
- case "wlroutput.testConfiguration":
- handleApplyConfiguration(conn, req, manager, true)
- case "wlroutput.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) {
- models.Respond(conn, req.ID, manager.GetState())
-}
-
-func handleApplyConfiguration(conn net.Conn, req models.Request, manager *Manager, test bool) {
- headsParam, ok := models.Get[any](req, "heads")
- if !ok {
- models.RespondError(conn, req.ID, "missing 'heads' parameter")
- return
- }
-
- headsJSON, err := json.Marshal(headsParam)
- if err != nil {
- models.RespondError(conn, req.ID, "invalid 'heads' parameter format")
- return
- }
-
- var heads []HeadConfig
- if err := json.Unmarshal(headsJSON, &heads); err != nil {
- models.RespondError(conn, req.ID, fmt.Sprintf("invalid heads configuration: %v", err))
- return
- }
-
- if err := manager.ApplyConfiguration(heads, test); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- msg := "configuration applied"
- if test {
- msg = "configuration test succeeded"
- }
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: msg})
-}
-
-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
- }
- }
-}
-
-func (m *Manager) ApplyConfiguration(heads []HeadConfig, test bool) error {
- if m.manager == nil {
- return fmt.Errorf("output manager not initialized")
- }
-
- resultChan := make(chan error, 1)
-
- m.post(func() {
- m.wlMutex.Lock()
- defer m.wlMutex.Unlock()
-
- config, err := m.manager.CreateConfiguration(m.serial)
- if err != nil {
- resultChan <- fmt.Errorf("failed to create configuration: %w", err)
- return
- }
-
- responded := false
-
- config.SetSucceededHandler(func(e wlr_output_management.ZwlrOutputConfigurationV1SucceededEvent) {
- if responded {
- return
- }
- responded = true
- log.Info("WlrOutput: configuration succeeded")
- config.Destroy()
- resultChan <- nil
- })
-
- config.SetFailedHandler(func(e wlr_output_management.ZwlrOutputConfigurationV1FailedEvent) {
- if responded {
- return
- }
- responded = true
- log.Warn("WlrOutput: configuration failed")
- config.Destroy()
- resultChan <- fmt.Errorf("compositor rejected configuration")
- })
-
- config.SetCancelledHandler(func(e wlr_output_management.ZwlrOutputConfigurationV1CancelledEvent) {
- if responded {
- return
- }
- responded = true
- log.Warn("WlrOutput: configuration cancelled")
- config.Destroy()
- resultChan <- fmt.Errorf("configuration cancelled (outdated serial)")
- })
-
- time.AfterFunc(time.Second, func() {
- m.post(func() {
- if responded {
- return
- }
- responded = true
- config.Destroy()
- resultChan <- fmt.Errorf("timeout waiting for configuration response")
- })
- })
-
- headsByName := make(map[string]*headState)
- m.heads.Range(func(key uint32, head *headState) bool {
- if !head.finished {
- headsByName[head.name] = head
- }
- return true
- })
-
- for _, headCfg := range heads {
- head, exists := headsByName[headCfg.Name]
- if !exists {
- config.Destroy()
- resultChan <- fmt.Errorf("head not found: %s", headCfg.Name)
- return
- }
-
- if !headCfg.Enabled {
- if err := config.DisableHead(head.handle); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to disable head %s: %w", headCfg.Name, err)
- return
- }
- continue
- }
-
- headConfig, err := config.EnableHead(head.handle)
- if err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to enable head %s: %w", headCfg.Name, err)
- return
- }
-
- if headCfg.ModeID != nil {
- mode, exists := m.modes.Load(*headCfg.ModeID)
-
- if !exists {
- config.Destroy()
- resultChan <- fmt.Errorf("mode not found: %d", *headCfg.ModeID)
- return
- }
-
- if err := headConfig.SetMode(mode.handle); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to set mode for %s: %w", headCfg.Name, err)
- return
- }
- } else if headCfg.CustomMode != nil {
- if err := headConfig.SetCustomMode(
- headCfg.CustomMode.Width,
- headCfg.CustomMode.Height,
- headCfg.CustomMode.Refresh,
- ); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to set custom mode for %s: %w", headCfg.Name, err)
- return
- }
- }
-
- if headCfg.Position != nil {
- if err := headConfig.SetPosition(headCfg.Position.X, headCfg.Position.Y); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to set position for %s: %w", headCfg.Name, err)
- return
- }
- }
-
- if headCfg.Transform != nil {
- if err := headConfig.SetTransform(*headCfg.Transform); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to set transform for %s: %w", headCfg.Name, err)
- return
- }
- }
-
- if headCfg.Scale != nil {
- if err := headConfig.SetScale(*headCfg.Scale); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to set scale for %s: %w", headCfg.Name, err)
- return
- }
- }
-
- if headCfg.AdaptiveSync != nil {
- if err := headConfig.SetAdaptiveSync(*headCfg.AdaptiveSync); err != nil {
- config.Destroy()
- resultChan <- fmt.Errorf("failed to set adaptive sync for %s: %w", headCfg.Name, err)
- return
- }
- }
- }
-
- var applyErr error
- if test {
- applyErr = config.Test()
- } else {
- applyErr = config.Apply()
- }
-
- if applyErr != nil {
- responded = true
- config.Destroy()
- action := "apply"
- if test {
- action = "test"
- }
- resultChan <- fmt.Errorf("failed to %s configuration: %w", action, applyErr)
- return
- }
- })
-
- return <-resultChan
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager.go
deleted file mode 100644
index cbd89a3..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager.go
+++ /dev/null
@@ -1,492 +0,0 @@
-package wlroutput
-
-import (
- "fmt"
- "time"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/log"
- "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/wlr_output_management"
- wlclient "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
-)
-
-func NewManager(display wlclient.WaylandDisplay) (*Manager, error) {
- m := &Manager{
- display: display,
- ctx: display.Context(),
- cmdq: make(chan cmd, 512),
- stopChan: make(chan struct{}),
- dirty: make(chan struct{}, 1),
- fatalError: make(chan error, 1),
- }
-
- m.wg.Add(1)
- go m.waylandActor()
-
- if err := m.setupRegistry(); err != nil {
- close(m.stopChan)
- m.wg.Wait()
- return nil, err
- }
-
- m.updateState()
-
- m.notifierWg.Add(1)
- go m.notifier()
-
- return m, nil
-}
-
-func (m *Manager) post(fn func()) {
- select {
- case m.cmdq <- cmd{fn: fn}:
- default:
- log.Warn("WlrOutput actor command queue full, dropping command")
- }
-}
-
-func (m *Manager) waylandActor() {
- defer m.wg.Done()
- defer func() {
- if r := recover(); r != nil {
- err := fmt.Errorf("waylandActor panic: %v", r)
- log.Errorf("WlrOutput: %v", err)
-
- select {
- case m.fatalError <- err:
- default:
- }
-
- select {
- case <-m.stopChan:
- default:
- close(m.stopChan)
- }
- }
- }()
-
- for {
- select {
- case <-m.stopChan:
- return
- case c := <-m.cmdq:
- func() {
- defer func() {
- if r := recover(); r != nil {
- log.Errorf("WlrOutput: command execution panic: %v", r)
- }
- }()
- c.fn()
- }()
- }
- }
-}
-
-func (m *Manager) setupRegistry() error {
- log.Info("WlrOutput: starting registry setup")
-
- registry, err := m.display.GetRegistry()
- if err != nil {
- return fmt.Errorf("failed to get registry: %w", err)
- }
- m.registry = registry
-
- registry.SetGlobalHandler(func(e wlclient.RegistryGlobalEvent) {
- if e.Interface == wlr_output_management.ZwlrOutputManagerV1InterfaceName {
- log.Infof("WlrOutput: found %s", wlr_output_management.ZwlrOutputManagerV1InterfaceName)
- manager := wlr_output_management.NewZwlrOutputManagerV1(m.ctx)
- version := e.Version
- if version > 4 {
- version = 4
- }
-
- manager.SetHeadHandler(func(e wlr_output_management.ZwlrOutputManagerV1HeadEvent) {
- m.handleHead(e)
- })
-
- manager.SetDoneHandler(func(e wlr_output_management.ZwlrOutputManagerV1DoneEvent) {
- log.Debugf("WlrOutput: done event received (serial=%d)", e.Serial)
- m.serial = e.Serial
- m.post(func() {
- m.updateState()
- })
- })
-
- manager.SetFinishedHandler(func(e wlr_output_management.ZwlrOutputManagerV1FinishedEvent) {
- log.Info("WlrOutput: finished event received")
- })
-
- if err := registry.Bind(e.Name, e.Interface, version, manager); err == nil {
- m.manager = manager
- log.Info("WlrOutput: manager bound successfully")
- } else {
- log.Errorf("WlrOutput: failed to bind manager: %v", err)
- }
- }
- })
-
- log.Info("WlrOutput: registry setup complete (events will be processed async)")
- return nil
-}
-
-func (m *Manager) handleHead(e wlr_output_management.ZwlrOutputManagerV1HeadEvent) {
- handle := e.Head
- headID := handle.ID()
-
- log.Debugf("WlrOutput: New head (id=%d)", headID)
-
- head := &headState{
- id: headID,
- handle: handle,
- modeIDs: make([]uint32, 0),
- }
-
- m.heads.Store(headID, head)
-
- handle.SetNameHandler(func(e wlr_output_management.ZwlrOutputHeadV1NameEvent) {
- log.Debugf("WlrOutput: Head %d name: %s", headID, e.Name)
- head.name = e.Name
- head.ready = true
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetDescriptionHandler(func(e wlr_output_management.ZwlrOutputHeadV1DescriptionEvent) {
- log.Debugf("WlrOutput: Head %d description: %s", headID, e.Description)
- head.description = e.Description
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetPhysicalSizeHandler(func(e wlr_output_management.ZwlrOutputHeadV1PhysicalSizeEvent) {
- log.Debugf("WlrOutput: Head %d physical size: %dx%d", headID, e.Width, e.Height)
- head.physicalWidth = e.Width
- head.physicalHeight = e.Height
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetModeHandler(func(e wlr_output_management.ZwlrOutputHeadV1ModeEvent) {
- m.handleMode(headID, e)
- })
-
- handle.SetEnabledHandler(func(e wlr_output_management.ZwlrOutputHeadV1EnabledEvent) {
- log.Debugf("WlrOutput: Head %d enabled: %d", headID, e.Enabled)
- head.enabled = e.Enabled != 0
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetCurrentModeHandler(func(e wlr_output_management.ZwlrOutputHeadV1CurrentModeEvent) {
- modeID := e.Mode.ID()
- log.Debugf("WlrOutput: Head %d current mode: %d", headID, modeID)
- head.currentModeID = modeID
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetPositionHandler(func(e wlr_output_management.ZwlrOutputHeadV1PositionEvent) {
- log.Debugf("WlrOutput: Head %d position: %d,%d", headID, e.X, e.Y)
- head.x = e.X
- head.y = e.Y
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetTransformHandler(func(e wlr_output_management.ZwlrOutputHeadV1TransformEvent) {
- log.Debugf("WlrOutput: Head %d transform: %d", headID, e.Transform)
- head.transform = e.Transform
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetScaleHandler(func(e wlr_output_management.ZwlrOutputHeadV1ScaleEvent) {
- log.Debugf("WlrOutput: Head %d scale: %f", headID, e.Scale)
- head.scale = e.Scale
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetMakeHandler(func(e wlr_output_management.ZwlrOutputHeadV1MakeEvent) {
- log.Debugf("WlrOutput: Head %d make: %s", headID, e.Make)
- head.make = e.Make
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetModelHandler(func(e wlr_output_management.ZwlrOutputHeadV1ModelEvent) {
- log.Debugf("WlrOutput: Head %d model: %s", headID, e.Model)
- head.model = e.Model
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetSerialNumberHandler(func(e wlr_output_management.ZwlrOutputHeadV1SerialNumberEvent) {
- log.Debugf("WlrOutput: Head %d serial: %s", headID, e.SerialNumber)
- head.serialNumber = e.SerialNumber
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetAdaptiveSyncHandler(func(e wlr_output_management.ZwlrOutputHeadV1AdaptiveSyncEvent) {
- log.Debugf("WlrOutput: Head %d adaptive sync: %d", headID, e.State)
- head.adaptiveSync = e.State
- head.adaptiveSyncSupported = true
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetFinishedHandler(func(e wlr_output_management.ZwlrOutputHeadV1FinishedEvent) {
- log.Debugf("WlrOutput: Head %d finished", headID)
- head.finished = true
-
- m.heads.Delete(headID)
-
- m.wlMutex.Lock()
- handle.Release()
- m.wlMutex.Unlock()
-
- m.post(func() {
- m.updateState()
- })
- })
-}
-
-func (m *Manager) handleMode(headID uint32, e wlr_output_management.ZwlrOutputHeadV1ModeEvent) {
- handle := e.Mode
- modeID := handle.ID()
-
- log.Debugf("WlrOutput: Head %d new mode (id=%d)", headID, modeID)
-
- mode := &modeState{
- id: modeID,
- handle: handle,
- }
-
- m.modes.Store(modeID, mode)
-
- if head, ok := m.heads.Load(headID); ok {
- head.modeIDs = append(head.modeIDs, modeID)
- m.heads.Store(headID, head)
- }
-
- handle.SetSizeHandler(func(e wlr_output_management.ZwlrOutputModeV1SizeEvent) {
- log.Debugf("WlrOutput: Mode %d size: %dx%d", modeID, e.Width, e.Height)
- mode.width = e.Width
- mode.height = e.Height
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetRefreshHandler(func(e wlr_output_management.ZwlrOutputModeV1RefreshEvent) {
- log.Debugf("WlrOutput: Mode %d refresh: %d", modeID, e.Refresh)
- mode.refresh = e.Refresh
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetPreferredHandler(func(e wlr_output_management.ZwlrOutputModeV1PreferredEvent) {
- log.Debugf("WlrOutput: Mode %d preferred", modeID)
- mode.preferred = true
- m.post(func() {
- m.updateState()
- })
- })
-
- handle.SetFinishedHandler(func(e wlr_output_management.ZwlrOutputModeV1FinishedEvent) {
- log.Debugf("WlrOutput: Mode %d finished", modeID)
- mode.finished = true
-
- m.modes.Delete(modeID)
-
- m.wlMutex.Lock()
- handle.Release()
- m.wlMutex.Unlock()
-
- m.post(func() {
- m.updateState()
- })
- })
-}
-
-func (m *Manager) updateState() {
- outputs := make([]Output, 0)
-
- m.heads.Range(func(key uint32, head *headState) bool {
- if head.finished {
- return true
- }
-
- if !head.ready {
- return true
- }
-
- modes := make([]OutputMode, 0)
- var currentMode *OutputMode
-
- for _, modeID := range head.modeIDs {
- mode, exists := m.modes.Load(modeID)
- if !exists {
- continue
- }
- if mode.finished {
- continue
- }
-
- outMode := OutputMode{
- Width: mode.width,
- Height: mode.height,
- Refresh: mode.refresh,
- Preferred: mode.preferred,
- ID: modeID,
- }
- modes = append(modes, outMode)
-
- if modeID == head.currentModeID {
- currentMode = &outMode
- }
- }
-
- output := Output{
- Name: head.name,
- Description: head.description,
- Make: head.make,
- Model: head.model,
- SerialNumber: head.serialNumber,
- PhysicalWidth: head.physicalWidth,
- PhysicalHeight: head.physicalHeight,
- Enabled: head.enabled,
- X: head.x,
- Y: head.y,
- Transform: head.transform,
- Scale: head.scale,
- CurrentMode: currentMode,
- Modes: modes,
- AdaptiveSync: head.adaptiveSync,
- AdaptiveSyncSupported: head.adaptiveSyncSupported,
- ID: head.id,
- }
- outputs = append(outputs, output)
- return true
- })
-
- newState := State{
- Outputs: outputs,
- Serial: m.serial,
- }
-
- m.stateMutex.Lock()
- m.state = &newState
- m.stateMutex.Unlock()
-
- m.notifySubscribers()
-}
-
-func (m *Manager) notifier() {
- defer m.notifierWg.Done()
- defer func() {
- if r := recover(); r != nil {
- err := fmt.Errorf("notifier panic: %v", r)
- log.Errorf("WlrOutput: %v", err)
-
- select {
- case m.fatalError <- err:
- default:
- }
-
- select {
- case <-m.stopChan:
- default:
- close(m.stopChan)
- }
- }
- }()
-
- 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("WlrOutput: subscriber channel full, dropping update")
- }
- return true
- })
-
- stateCopy := currentState
- m.lastNotified = &stateCopy
- pending = false
- }
- }
-}
-
-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.modes.Range(func(key uint32, mode *modeState) bool {
- if mode.handle != nil {
- mode.handle.Release()
- }
- m.modes.Delete(key)
- return true
- })
-
- m.heads.Range(func(key uint32, head *headState) bool {
- if head.handle != nil {
- head.handle.Release()
- }
- m.heads.Delete(key)
- return true
- })
-
- if m.manager != nil {
- m.manager.Stop()
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager_test.go
deleted file mode 100644
index e90c70c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/manager_test.go
+++ /dev/null
@@ -1,414 +0,0 @@
-package wlroutput
-
-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{Serial: 1}
- assert.True(t, stateChanged(s, nil))
- assert.True(t, stateChanged(nil, s))
-}
-
-func TestStateChanged_SerialDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{}}
- b := &State{Serial: 2, Outputs: []Output{}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputCountDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1"}}}
- b := &State{Serial: 1, Outputs: []Output{}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputNameDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Enabled: true}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "HDMI-A-1", Enabled: true}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputEnabledDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Enabled: true}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Enabled: false}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputPositionDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", X: 0, Y: 0}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", X: 1920, Y: 0}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputTransformDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Transform: 0}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Transform: 1}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputScaleDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Scale: 1.0}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Scale: 2.0}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_OutputAdaptiveSyncDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", AdaptiveSync: 0}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", AdaptiveSync: 1}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_CurrentModeNilVsNonNil(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", CurrentMode: nil}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", CurrentMode: &OutputMode{Width: 1920}}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_CurrentModeDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{
- Name: "eDP-1",
- CurrentMode: &OutputMode{Width: 1920, Height: 1080, Refresh: 60000},
- }}}
- b := &State{Serial: 1, Outputs: []Output{{
- Name: "eDP-1",
- CurrentMode: &OutputMode{Width: 2560, Height: 1440, Refresh: 60000},
- }}}
- assert.True(t, stateChanged(a, b))
-
- b.Outputs[0].CurrentMode.Width = 1920
- b.Outputs[0].CurrentMode.Height = 1080
- b.Outputs[0].CurrentMode.Refresh = 144000
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_ModesLengthDiffers(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Modes: []OutputMode{{Width: 1920}}}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", Modes: []OutputMode{{Width: 1920}, {Width: 1280}}}}}
- assert.True(t, stateChanged(a, b))
-}
-
-func TestStateChanged_Equal(t *testing.T) {
- mode := OutputMode{Width: 1920, Height: 1080, Refresh: 60000, Preferred: true}
- a := &State{
- Serial: 5,
- Outputs: []Output{{
- Name: "eDP-1",
- Description: "Built-in display",
- Make: "BOE",
- Model: "0x0ABC",
- SerialNumber: "12345",
- PhysicalWidth: 309,
- PhysicalHeight: 174,
- Enabled: true,
- X: 0,
- Y: 0,
- Transform: 0,
- Scale: 1.0,
- CurrentMode: &mode,
- Modes: []OutputMode{mode},
- AdaptiveSync: 0,
- }},
- }
- b := &State{
- Serial: 5,
- Outputs: []Output{{
- Name: "eDP-1",
- Description: "Built-in display",
- Make: "BOE",
- Model: "0x0ABC",
- SerialNumber: "12345",
- PhysicalWidth: 309,
- PhysicalHeight: 174,
- Enabled: true,
- X: 0,
- Y: 0,
- Transform: 0,
- Scale: 1.0,
- CurrentMode: &mode,
- Modes: []OutputMode{mode},
- AdaptiveSync: 0,
- }},
- }
- assert.False(t, stateChanged(a, b))
-}
-
-func TestManager_ConcurrentGetState(t *testing.T) {
- m := &Manager{
- state: &State{
- Serial: 1,
- Outputs: []Output{{Name: "eDP-1", Enabled: true}},
- },
- }
-
- 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.Serial
- _ = 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{
- Serial: uint32(j),
- Outputs: []Output{{Name: "eDP-1", Scale: float64(j % 3)}},
- }
- 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_SyncmapHeadsConcurrentAccess(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 := &headState{
- id: key,
- name: "test-head",
- enabled: j%2 == 0,
- scale: float64(j % 3),
- modeIDs: []uint32{uint32(j)},
- }
- m.heads.Store(key, state)
-
- if loaded, ok := m.heads.Load(key); ok {
- assert.Equal(t, key, loaded.id)
- }
-
- m.heads.Range(func(k uint32, v *headState) bool {
- _ = v.name
- _ = v.enabled
- return true
- })
- }
-
- m.heads.Delete(key)
- }(i)
- }
-
- wg.Wait()
-}
-
-func TestManager_SyncmapModesConcurrentAccess(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 := &modeState{
- id: key,
- width: int32(1920 + j),
- height: int32(1080 + j),
- refresh: 60000,
- preferred: j == 0,
- }
- m.modes.Store(key, state)
-
- if loaded, ok := m.modes.Load(key); ok {
- assert.Equal(t, key, loaded.id)
- }
-
- m.modes.Range(func(k uint32, v *modeState) bool {
- _ = v.width
- _ = v.height
- return true
- })
- }
-
- m.modes.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.Equal(t, uint32(0), s.Serial)
-}
-
-func TestManager_FatalErrorChannel(t *testing.T) {
- m := &Manager{
- fatalError: make(chan error, 1),
- }
-
- ch := m.FatalError()
- assert.NotNil(t, ch)
-
- m.fatalError <- assert.AnError
- err := <-ch
- assert.Error(t, err)
-}
-
-func TestOutputMode_Fields(t *testing.T) {
- mode := OutputMode{
- Width: 1920,
- Height: 1080,
- Refresh: 60000,
- Preferred: true,
- ID: 42,
- }
-
- assert.Equal(t, int32(1920), mode.Width)
- assert.Equal(t, int32(1080), mode.Height)
- assert.Equal(t, int32(60000), mode.Refresh)
- assert.True(t, mode.Preferred)
- assert.Equal(t, uint32(42), mode.ID)
-}
-
-func TestOutput_Fields(t *testing.T) {
- out := Output{
- Name: "eDP-1",
- Description: "Built-in display",
- Make: "BOE",
- Model: "0x0ABC",
- SerialNumber: "12345",
- PhysicalWidth: 309,
- PhysicalHeight: 174,
- Enabled: true,
- X: 0,
- Y: 0,
- Transform: 0,
- Scale: 1.5,
- AdaptiveSync: 1,
- ID: 1,
- }
-
- assert.Equal(t, "eDP-1", out.Name)
- assert.Equal(t, "Built-in display", out.Description)
- assert.True(t, out.Enabled)
- assert.Equal(t, float64(1.5), out.Scale)
- assert.Equal(t, uint32(1), out.AdaptiveSync)
-}
-
-func TestHeadState_ModeIDsSlice(t *testing.T) {
- head := &headState{
- id: 1,
- modeIDs: make([]uint32, 0),
- }
-
- head.modeIDs = append(head.modeIDs, 1, 2, 3)
- assert.Len(t, head.modeIDs, 3)
- assert.Equal(t, uint32(1), head.modeIDs[0])
-}
-
-func TestStateChanged_BothCurrentModeNil(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", CurrentMode: nil}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1", CurrentMode: nil}}}
- assert.False(t, stateChanged(a, b))
-}
-
-func TestStateChanged_IndexOutOfBounds(t *testing.T) {
- a := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1"}}}
- b := &State{Serial: 1, Outputs: []Output{{Name: "eDP-1"}, {Name: "HDMI-A-1"}}}
- 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")
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/types.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/types.go
deleted file mode 100644
index 9c79b1a..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/wlroutput/types.go
+++ /dev/null
@@ -1,192 +0,0 @@
-package wlroutput
-
-import (
- "sync"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/wlr_output_management"
- wlclient "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
- "github.com/AvengeMedia/DankMaterialShell/core/pkg/syncmap"
-)
-
-type OutputMode struct {
- Width int32 `json:"width"`
- Height int32 `json:"height"`
- Refresh int32 `json:"refresh"`
- Preferred bool `json:"preferred"`
- ID uint32 `json:"id"`
-}
-
-type Output struct {
- Name string `json:"name"`
- Description string `json:"description"`
- Make string `json:"make"`
- Model string `json:"model"`
- SerialNumber string `json:"serialNumber"`
- PhysicalWidth int32 `json:"physicalWidth"`
- PhysicalHeight int32 `json:"physicalHeight"`
- Enabled bool `json:"enabled"`
- X int32 `json:"x"`
- Y int32 `json:"y"`
- Transform int32 `json:"transform"`
- Scale float64 `json:"scale"`
- CurrentMode *OutputMode `json:"currentMode"`
- Modes []OutputMode `json:"modes"`
- AdaptiveSync uint32 `json:"adaptiveSync"`
- AdaptiveSyncSupported bool `json:"adaptiveSyncSupported"`
- ID uint32 `json:"id"`
-}
-
-type State struct {
- Outputs []Output `json:"outputs"`
- Serial uint32 `json:"serial"`
-}
-
-type cmd struct {
- fn func()
-}
-
-type Manager struct {
- display wlclient.WaylandDisplay
- ctx *wlclient.Context
- registry *wlclient.Registry
- manager *wlr_output_management.ZwlrOutputManagerV1
-
- heads syncmap.Map[uint32, *headState]
- modes syncmap.Map[uint32, *modeState]
-
- serial uint32
-
- wlMutex sync.Mutex
- cmdq chan cmd
- 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
-
- fatalError chan error
-}
-
-type headState struct {
- id uint32
- handle *wlr_output_management.ZwlrOutputHeadV1
- name string
- description string
- make string
- model string
- serialNumber string
- physicalWidth int32
- physicalHeight int32
- enabled bool
- x int32
- y int32
- transform int32
- scale float64
- currentModeID uint32
- modeIDs []uint32
- adaptiveSync uint32
- adaptiveSyncSupported bool
- finished bool
- ready bool
-}
-
-type modeState struct {
- id uint32
- handle *wlr_output_management.ZwlrOutputModeV1
- width int32
- height int32
- refresh int32
- preferred bool
- finished bool
-}
-
-func (m *Manager) GetState() State {
- m.stateMutex.RLock()
- defer m.stateMutex.RUnlock()
- if m.state == nil {
- return State{
- Outputs: []Output{},
- Serial: 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 (m *Manager) FatalError() <-chan error {
- return m.fatalError
-}
-
-func stateChanged(old, new *State) bool {
- if old == nil || new == nil {
- return true
- }
- if old.Serial != new.Serial {
- return true
- }
- if len(old.Outputs) != len(new.Outputs) {
- return true
- }
- for i := range new.Outputs {
- if i >= len(old.Outputs) {
- return true
- }
- oldOut := &old.Outputs[i]
- newOut := &new.Outputs[i]
- if oldOut.Name != newOut.Name || oldOut.Enabled != newOut.Enabled {
- return true
- }
- if oldOut.X != newOut.X || oldOut.Y != newOut.Y {
- return true
- }
- if oldOut.Transform != newOut.Transform || oldOut.Scale != newOut.Scale {
- return true
- }
- if oldOut.AdaptiveSync != newOut.AdaptiveSync || oldOut.AdaptiveSyncSupported != newOut.AdaptiveSyncSupported {
- return true
- }
- if (oldOut.CurrentMode == nil) != (newOut.CurrentMode == nil) {
- return true
- }
- if oldOut.CurrentMode != nil && newOut.CurrentMode != nil {
- if oldOut.CurrentMode.Width != newOut.CurrentMode.Width ||
- oldOut.CurrentMode.Height != newOut.CurrentMode.Height ||
- oldOut.CurrentMode.Refresh != newOut.CurrentMode.Refresh {
- return true
- }
- }
- if len(oldOut.Modes) != len(newOut.Modes) {
- return true
- }
- }
- return false
-}