summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop
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/freedesktop
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/freedesktop')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions.go112
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions_test.go145
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/constants.go23
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers.go154
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers_test.go581
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager.go206
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager_test.go143
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver.go349
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver_test.go102
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types.go66
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types_test.go70
11 files changed, 0 insertions, 1951 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions.go
deleted file mode 100644
index 52515d1..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package freedesktop
-
-import (
- "fmt"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/utils"
- "github.com/godbus/dbus/v5"
-)
-
-func (m *Manager) SetIconFile(iconPath string) error {
- if !m.state.Accounts.Available || m.accountsObj == nil {
- return fmt.Errorf("accounts service not available")
- }
-
- err := m.accountsObj.Call(dbusAccountsUserInterface+".SetIconFile", 0, iconPath).Err
- if err != nil {
- return fmt.Errorf("failed to set icon file: %w", err)
- }
-
- m.updateAccountsState()
- return nil
-}
-
-func (m *Manager) SetRealName(name string) error {
- if !m.state.Accounts.Available || m.accountsObj == nil {
- return fmt.Errorf("accounts service not available")
- }
-
- err := m.accountsObj.Call(dbusAccountsUserInterface+".SetRealName", 0, name).Err
- if err != nil {
- return fmt.Errorf("failed to set real name: %w", err)
- }
-
- m.updateAccountsState()
- return nil
-}
-
-func (m *Manager) SetEmail(email string) error {
- if !m.state.Accounts.Available || m.accountsObj == nil {
- return fmt.Errorf("accounts service not available")
- }
-
- err := m.accountsObj.Call(dbusAccountsUserInterface+".SetEmail", 0, email).Err
- if err != nil {
- return fmt.Errorf("failed to set email: %w", err)
- }
-
- m.updateAccountsState()
- return nil
-}
-
-func (m *Manager) SetLanguage(language string) error {
- if !m.state.Accounts.Available || m.accountsObj == nil {
- return fmt.Errorf("accounts service not available")
- }
-
- err := m.accountsObj.Call(dbusAccountsUserInterface+".SetLanguage", 0, language).Err
- if err != nil {
- return fmt.Errorf("failed to set language: %w", err)
- }
-
- m.updateAccountsState()
- return nil
-}
-
-func (m *Manager) SetLocation(location string) error {
- if !m.state.Accounts.Available || m.accountsObj == nil {
- return fmt.Errorf("accounts service not available")
- }
-
- err := m.accountsObj.Call(dbusAccountsUserInterface+".SetLocation", 0, location).Err
- if err != nil {
- return fmt.Errorf("failed to set location: %w", err)
- }
-
- m.updateAccountsState()
- return nil
-}
-
-func (m *Manager) GetUserIconFile(username string) (string, error) {
- if m.systemConn == nil {
- return "", fmt.Errorf("accounts service not available")
- }
-
- accountsManager := m.systemConn.Object(dbusAccountsDest, dbus.ObjectPath(dbusAccountsPath))
-
- var userPath dbus.ObjectPath
- err := accountsManager.Call(dbusAccountsInterface+".FindUserByName", 0, username).Store(&userPath)
- if err != nil {
- return "", fmt.Errorf("user not found: %w", err)
- }
-
- userObj := m.systemConn.Object(dbusAccountsDest, userPath)
- variant, err := userObj.GetProperty(dbusAccountsUserInterface + ".IconFile")
- if err != nil {
- return "", err
- }
-
- var iconFile string
- if err := variant.Store(&iconFile); err != nil {
- return "", err
- }
-
- return iconFile, nil
-}
-
-func (m *Manager) SetIconTheme(iconTheme string) error {
- if err := utils.GsettingsSet("org.gnome.desktop.interface", "icon-theme", iconTheme); err != nil {
- return fmt.Errorf("failed to set icon theme: %w", err)
- }
- return nil
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions_test.go
deleted file mode 100644
index e2c21e8..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/actions_test.go
+++ /dev/null
@@ -1,145 +0,0 @@
-package freedesktop
-
-import (
- "sync"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestManager_SetIconFile(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.SetIconFile("/path/to/icon.png")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- })
-}
-
-func TestManager_SetRealName(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.SetRealName("New Name")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- })
-}
-
-func TestManager_SetEmail(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.SetEmail("test@example.com")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- })
-}
-
-func TestManager_SetLanguage(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.SetLanguage("en_US.UTF-8")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- })
-}
-
-func TestManager_SetLocation(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.SetLocation("Test Location")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- })
-}
-
-func TestManager_GetUserIconFile(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- iconFile, err := manager.GetUserIconFile("testuser")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- assert.Empty(t, iconFile)
- })
-}
-
-func TestManager_UpdateAccountsState(t *testing.T) {
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.updateAccountsState()
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "accounts service not available")
- })
-}
-
-func TestManager_UpdateSettingsState(t *testing.T) {
- t.Run("settings not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Settings: SettingsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- err := manager.updateSettingsState()
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "settings portal not available")
- })
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/constants.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/constants.go
deleted file mode 100644
index 12db87b..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/constants.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package freedesktop
-
-const (
- dbusAccountsDest = "org.freedesktop.Accounts"
- dbusAccountsPath = "/org/freedesktop/Accounts"
- dbusAccountsInterface = "org.freedesktop.Accounts"
- dbusAccountsUserInterface = "org.freedesktop.Accounts.User"
-
- dbusPortalDest = "org.freedesktop.portal.Desktop"
- dbusPortalPath = "/org/freedesktop/portal/desktop"
- dbusPortalSettingsInterface = "org.freedesktop.portal.Settings"
-
- dbusPropsInterface = "org.freedesktop.DBus.Properties"
-
- dbusScreensaverName = "org.freedesktop.ScreenSaver"
- dbusScreensaverPath = "/ScreenSaver"
- dbusScreensaverPath2 = "/org/freedesktop/ScreenSaver"
- dbusScreensaverInterface = "org.freedesktop.ScreenSaver"
-
- dbusGnomeScreensaverName = "org.gnome.ScreenSaver"
- dbusGnomeScreensaverPath = "/org/gnome/ScreenSaver"
- dbusGnomeScreensaverInterface = "org.gnome.ScreenSaver"
-)
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers.go
deleted file mode 100644
index c3090fa..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package freedesktop
-
-import (
- "fmt"
- "net"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
- "github.com/AvengeMedia/DankMaterialShell/core/internal/server/params"
-)
-
-func HandleRequest(conn net.Conn, req models.Request, manager *Manager) {
- switch req.Method {
- case "freedesktop.getState":
- handleGetState(conn, req, manager)
- case "freedesktop.accounts.setIconFile":
- handleSetIconFile(conn, req, manager)
- case "freedesktop.accounts.setRealName":
- handleSetRealName(conn, req, manager)
- case "freedesktop.accounts.setEmail":
- handleSetEmail(conn, req, manager)
- case "freedesktop.accounts.setLanguage":
- handleSetLanguage(conn, req, manager)
- case "freedesktop.accounts.setLocation":
- handleSetLocation(conn, req, manager)
- case "freedesktop.accounts.getUserIconFile":
- handleGetUserIconFile(conn, req, manager)
- case "freedesktop.settings.getColorScheme":
- handleGetColorScheme(conn, req, manager)
- case "freedesktop.settings.setIconTheme":
- handleSetIconTheme(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 handleSetIconFile(conn net.Conn, req models.Request, manager *Manager) {
- iconPath, err := params.String(req.Params, "path")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- if err := manager.SetIconFile(iconPath); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "icon file set"})
-}
-
-func handleSetRealName(conn net.Conn, req models.Request, manager *Manager) {
- name, err := params.String(req.Params, "name")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- if err := manager.SetRealName(name); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "real name set"})
-}
-
-func handleSetEmail(conn net.Conn, req models.Request, manager *Manager) {
- email, err := params.String(req.Params, "email")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- if err := manager.SetEmail(email); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "email set"})
-}
-
-func handleSetLanguage(conn net.Conn, req models.Request, manager *Manager) {
- language, err := params.String(req.Params, "language")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- if err := manager.SetLanguage(language); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "language set"})
-}
-
-func handleSetLocation(conn net.Conn, req models.Request, manager *Manager) {
- location, err := params.String(req.Params, "location")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- if err := manager.SetLocation(location); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "location set"})
-}
-
-func handleGetUserIconFile(conn net.Conn, req models.Request, manager *Manager) {
- username, err := params.String(req.Params, "username")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- iconFile, err := manager.GetUserIconFile(username)
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Value: iconFile})
-}
-
-func handleGetColorScheme(conn net.Conn, req models.Request, manager *Manager) {
- if err := manager.updateSettingsState(); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- state := manager.GetState()
- models.Respond(conn, req.ID, map[string]uint32{"colorScheme": state.Settings.ColorScheme})
-}
-
-func handleSetIconTheme(conn net.Conn, req models.Request, manager *Manager) {
- iconTheme, err := params.String(req.Params, "iconTheme")
- if err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- if err := manager.SetIconTheme(iconTheme); err != nil {
- models.RespondError(conn, req.ID, err.Error())
- return
- }
-
- models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "icon theme set"})
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers_test.go
deleted file mode 100644
index f2cb5a2..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/handlers_test.go
+++ /dev/null
@@ -1,581 +0,0 @@
-package freedesktop
-
-import (
- "bytes"
- "encoding/json"
- "net"
- "sync"
- "testing"
-
- mockdbus "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/github.com/godbus/dbus/v5"
- "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
- "github.com/godbus/dbus/v5"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
-)
-
-type mockNetConn struct {
- net.Conn
- readBuf *bytes.Buffer
- writeBuf *bytes.Buffer
- closed bool
-}
-
-func newMockNetConn() *mockNetConn {
- return &mockNetConn{
- readBuf: &bytes.Buffer{},
- writeBuf: &bytes.Buffer{},
- }
-}
-
-func (m *mockNetConn) Read(b []byte) (n int, err error) {
- return m.readBuf.Read(b)
-}
-
-func (m *mockNetConn) Write(b []byte) (n int, err error) {
- return m.writeBuf.Write(b)
-}
-
-func (m *mockNetConn) Close() error {
- m.closed = true
- return nil
-}
-
-func mockGetAllAccountsProperties() *dbus.Call {
- props := map[string]dbus.Variant{
- "IconFile": dbus.MakeVariant("/path/to/icon.png"),
- "RealName": dbus.MakeVariant("Test"),
- "UserName": dbus.MakeVariant("test"),
- "AccountType": dbus.MakeVariant(int32(0)),
- "HomeDirectory": dbus.MakeVariant("/home/test"),
- "Shell": dbus.MakeVariant("/bin/bash"),
- "Email": dbus.MakeVariant(""),
- "Language": dbus.MakeVariant(""),
- "Location": dbus.MakeVariant(""),
- "Locked": dbus.MakeVariant(false),
- "PasswordMode": dbus.MakeVariant(int32(1)),
- }
- return &dbus.Call{Err: nil, Body: []any{props}}
-}
-
-func TestRespondError_Freedesktop(t *testing.T) {
- conn := newMockNetConn()
- models.RespondError(conn, 123, "test error")
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Equal(t, "test error", resp.Error)
- assert.Nil(t, resp.Result)
-}
-
-func TestRespond_Freedesktop(t *testing.T) {
- conn := newMockNetConn()
- result := models.SuccessResult{Success: true, Message: "test"}
- models.Respond(conn, 123, result)
-
- var resp models.Response[models.SuccessResult]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- require.NotNil(t, resp.Result)
- assert.True(t, resp.Result.Success)
- assert.Equal(t, "test", resp.Result.Message)
-}
-
-func TestHandleGetState(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- UserName: "testuser",
- RealName: "Test User",
- UID: 1000,
- },
- Settings: SettingsState{
- Available: true,
- ColorScheme: 1,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{ID: 123, Method: "freedesktop.getState"}
-
- handleGetState(conn, req, manager)
-
- var resp models.Response[FreedeskState]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- require.NotNil(t, resp.Result)
- assert.True(t, resp.Result.Accounts.Available)
- assert.Equal(t, "testuser", resp.Result.Accounts.UserName)
- assert.True(t, resp.Result.Settings.Available)
- assert.Equal(t, uint32(1), resp.Result.Settings.ColorScheme)
-}
-
-func TestHandleSetIconFile(t *testing.T) {
- t.Run("missing path parameter", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setIconFile",
- Params: map[string]any{},
- }
-
- handleSetIconFile(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "missing or invalid 'path' parameter")
- })
-
- t.Run("successful set icon file", func(t *testing.T) {
- mockAccountsObj := mockdbus.NewMockBusObject(t)
- mockCall := &dbus.Call{Err: nil}
- mockAccountsObj.EXPECT().Call("org.freedesktop.Accounts.User.SetIconFile", dbus.Flags(0), "/path/to/icon.png").Return(mockCall)
- mockAccountsObj.EXPECT().CallWithContext(mock.Anything, "org.freedesktop.DBus.Properties.GetAll", dbus.Flags(0), "org.freedesktop.Accounts.User").Return(mockGetAllAccountsProperties())
-
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- },
- },
- stateMutex: sync.RWMutex{},
- accountsObj: mockAccountsObj,
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setIconFile",
- Params: map[string]any{
- "path": "/path/to/icon.png",
- },
- }
-
- handleSetIconFile(conn, req, manager)
-
- var resp models.Response[models.SuccessResult]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- require.NotNil(t, resp.Result)
- assert.True(t, resp.Result.Success)
- assert.Equal(t, "icon file set", resp.Result.Message)
- })
-
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setIconFile",
- Params: map[string]any{
- "path": "/path/to/icon.png",
- },
- }
-
- handleSetIconFile(conn, req, manager)
-
- var resp models.Response[models.SuccessResult]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "accounts service not available")
- })
-}
-
-func TestHandleSetRealName(t *testing.T) {
- t.Run("missing name parameter", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setRealName",
- Params: map[string]any{},
- }
-
- handleSetRealName(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "missing or invalid 'name' parameter")
- })
-
- t.Run("successful set real name", func(t *testing.T) {
- mockAccountsObj := mockdbus.NewMockBusObject(t)
- mockCall := &dbus.Call{Err: nil}
- mockAccountsObj.EXPECT().Call("org.freedesktop.Accounts.User.SetRealName", dbus.Flags(0), "New Name").Return(mockCall)
- mockAccountsObj.EXPECT().CallWithContext(mock.Anything, "org.freedesktop.DBus.Properties.GetAll", dbus.Flags(0), "org.freedesktop.Accounts.User").Return(mockGetAllAccountsProperties())
-
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- },
- },
- stateMutex: sync.RWMutex{},
- accountsObj: mockAccountsObj,
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setRealName",
- Params: map[string]any{
- "name": "New Name",
- },
- }
-
- handleSetRealName(conn, req, manager)
-
- var resp models.Response[models.SuccessResult]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- require.NotNil(t, resp.Result)
- assert.True(t, resp.Result.Success)
- assert.Equal(t, "real name set", resp.Result.Message)
- })
-}
-
-func TestHandleSetEmail(t *testing.T) {
- t.Run("missing email parameter", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setEmail",
- Params: map[string]any{},
- }
-
- handleSetEmail(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "missing or invalid 'email' parameter")
- })
-
- t.Run("successful set email", func(t *testing.T) {
- mockAccountsObj := mockdbus.NewMockBusObject(t)
- mockCall := &dbus.Call{Err: nil}
- mockAccountsObj.EXPECT().Call("org.freedesktop.Accounts.User.SetEmail", dbus.Flags(0), "test@example.com").Return(mockCall)
- mockAccountsObj.EXPECT().CallWithContext(mock.Anything, "org.freedesktop.DBus.Properties.GetAll", dbus.Flags(0), "org.freedesktop.Accounts.User").Return(mockGetAllAccountsProperties())
-
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- },
- },
- stateMutex: sync.RWMutex{},
- accountsObj: mockAccountsObj,
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setEmail",
- Params: map[string]any{
- "email": "test@example.com",
- },
- }
-
- handleSetEmail(conn, req, manager)
-
- var resp models.Response[models.SuccessResult]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- require.NotNil(t, resp.Result)
- assert.True(t, resp.Result.Success)
- assert.Equal(t, "email set", resp.Result.Message)
- })
-}
-
-func TestHandleSetLanguage(t *testing.T) {
- t.Run("missing language parameter", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setLanguage",
- Params: map[string]any{},
- }
-
- handleSetLanguage(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "missing or invalid 'language' parameter")
- })
-}
-
-func TestHandleSetLocation(t *testing.T) {
- t.Run("missing location parameter", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.setLocation",
- Params: map[string]any{},
- }
-
- handleSetLocation(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "missing or invalid 'location' parameter")
- })
-}
-
-func TestHandleGetUserIconFile(t *testing.T) {
- t.Run("missing username parameter", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.getUserIconFile",
- Params: map[string]any{},
- }
-
- handleGetUserIconFile(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "missing or invalid 'username' parameter")
- })
-
- t.Run("accounts not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.accounts.getUserIconFile",
- Params: map[string]any{
- "username": "testuser",
- },
- }
-
- handleGetUserIconFile(conn, req, manager)
-
- var resp models.Response[models.SuccessResult]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "accounts service not available")
- })
-}
-
-func TestHandleGetColorScheme(t *testing.T) {
- t.Run("settings not available", func(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Settings: SettingsState{
- Available: false,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- conn := newMockNetConn()
- req := models.Request{ID: 123, Method: "freedesktop.settings.getColorScheme"}
-
- handleGetColorScheme(conn, req, manager)
-
- var resp models.Response[map[string]uint32]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "settings portal not available")
- })
-
- t.Run("successful get color scheme", func(t *testing.T) {
- mockSettingsObj := mockdbus.NewMockBusObject(t)
- mockCall := &dbus.Call{
- Err: nil,
- Body: []any{dbus.MakeVariant(uint32(1))},
- }
- mockSettingsObj.EXPECT().Call("org.freedesktop.portal.Settings.ReadOne", dbus.Flags(0), "org.freedesktop.appearance", "color-scheme").Return(mockCall)
-
- manager := &Manager{
- state: &FreedeskState{
- Settings: SettingsState{
- Available: true,
- },
- },
- stateMutex: sync.RWMutex{},
- settingsObj: mockSettingsObj,
- }
-
- conn := newMockNetConn()
- req := models.Request{ID: 123, Method: "freedesktop.settings.getColorScheme"}
-
- handleGetColorScheme(conn, req, manager)
-
- var resp models.Response[map[string]uint32]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- require.NotNil(t, resp.Result)
- assert.Equal(t, uint32(1), (*resp.Result)["colorScheme"])
- })
-}
-
-func TestHandleRequest(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- UserName: "testuser",
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- t.Run("unknown method", func(t *testing.T) {
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.unknown",
- }
-
- HandleRequest(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Contains(t, resp.Error, "unknown method")
- })
-
- t.Run("valid method - getState", func(t *testing.T) {
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: "freedesktop.getState",
- }
-
- HandleRequest(conn, req, manager)
-
- var resp models.Response[FreedeskState]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- assert.Empty(t, resp.Error)
- })
-
- t.Run("all method routes", func(t *testing.T) {
- tests := []string{
- "freedesktop.accounts.setIconFile",
- "freedesktop.accounts.setRealName",
- "freedesktop.accounts.setEmail",
- "freedesktop.accounts.setLanguage",
- "freedesktop.accounts.setLocation",
- "freedesktop.accounts.getUserIconFile",
- "freedesktop.settings.getColorScheme",
- }
-
- for _, method := range tests {
- conn := newMockNetConn()
- req := models.Request{
- ID: 123,
- Method: method,
- Params: map[string]any{},
- }
-
- HandleRequest(conn, req, manager)
-
- var resp models.Response[any]
- err := json.NewDecoder(conn.writeBuf).Decode(&resp)
- require.NoError(t, err)
-
- assert.Equal(t, 123, resp.ID)
- // Will have errors due to missing params or service unavailable
- // but the method routing should work
- }
- })
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager.go
deleted file mode 100644
index 054f859..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager.go
+++ /dev/null
@@ -1,206 +0,0 @@
-package freedesktop
-
-import (
- "context"
- "fmt"
- "os"
- "sync"
-
- "github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
- "github.com/godbus/dbus/v5"
-)
-
-func NewManager() (*Manager, error) {
- systemConn, err := dbus.ConnectSystemBus()
- if err != nil {
- return nil, fmt.Errorf("failed to connect to system bus: %w", err)
- }
-
- sessionConn, err := dbus.ConnectSessionBus()
- if err != nil {
- sessionConn = nil
- }
-
- m := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{},
- Settings: SettingsState{},
- Screensaver: ScreensaverState{},
- },
- stateMutex: sync.RWMutex{},
- systemConn: systemConn,
- sessionConn: sessionConn,
- currentUID: uint64(os.Getuid()),
- }
-
- m.initializeAccounts()
- m.initializeSettings()
- m.initializeScreensaver()
-
- return m, nil
-}
-
-func (m *Manager) initializeAccounts() error {
- accountsManager := m.systemConn.Object(dbusAccountsDest, dbus.ObjectPath(dbusAccountsPath))
-
- var userPath dbus.ObjectPath
- err := accountsManager.Call(dbusAccountsInterface+".FindUserById", 0, int64(m.currentUID)).Store(&userPath)
- if err != nil {
- m.stateMutex.Lock()
- m.state.Accounts.Available = false
- m.stateMutex.Unlock()
- return err
- }
-
- m.accountsObj = m.systemConn.Object(dbusAccountsDest, userPath)
-
- m.stateMutex.Lock()
- m.state.Accounts.Available = true
- m.state.Accounts.UserPath = string(userPath)
- m.state.Accounts.UID = m.currentUID
- m.stateMutex.Unlock()
-
- if err := m.updateAccountsState(); err != nil {
- return fmt.Errorf("failed to update accounts state: %w", err)
- }
-
- return nil
-}
-
-func (m *Manager) initializeSettings() error {
- if m.sessionConn == nil {
- m.stateMutex.Lock()
- m.state.Settings.Available = false
- m.stateMutex.Unlock()
- return fmt.Errorf("no session bus connection")
- }
-
- m.settingsObj = m.sessionConn.Object(dbusPortalDest, dbus.ObjectPath(dbusPortalPath))
-
- var variant dbus.Variant
- err := m.settingsObj.Call(dbusPortalSettingsInterface+".ReadOne", 0, "org.freedesktop.appearance", "color-scheme").Store(&variant)
- if err != nil {
- m.stateMutex.Lock()
- m.state.Settings.Available = false
- m.stateMutex.Unlock()
- return err
- }
-
- m.stateMutex.Lock()
- m.state.Settings.Available = true
- m.stateMutex.Unlock()
-
- if err := m.updateSettingsState(); err != nil {
- return fmt.Errorf("failed to update settings state: %w", err)
- }
-
- return nil
-}
-
-func (m *Manager) updateAccountsState() error {
- if !m.state.Accounts.Available || m.accountsObj == nil {
- return fmt.Errorf("accounts service not available")
- }
-
- ctx := context.Background()
- props, err := m.getAccountProperties(ctx)
- if err != nil {
- return err
- }
-
- m.stateMutex.Lock()
- defer m.stateMutex.Unlock()
-
- m.state.Accounts.IconFile = dbusutil.GetOr(props, "IconFile", "")
- m.state.Accounts.RealName = dbusutil.GetOr(props, "RealName", "")
- m.state.Accounts.UserName = dbusutil.GetOr(props, "UserName", "")
- m.state.Accounts.AccountType = dbusutil.GetOr(props, "AccountType", int32(0))
- m.state.Accounts.HomeDirectory = dbusutil.GetOr(props, "HomeDirectory", "")
- m.state.Accounts.Shell = dbusutil.GetOr(props, "Shell", "")
- m.state.Accounts.Email = dbusutil.GetOr(props, "Email", "")
- m.state.Accounts.Language = dbusutil.GetOr(props, "Language", "")
- m.state.Accounts.Location = dbusutil.GetOr(props, "Location", "")
- m.state.Accounts.Locked = dbusutil.GetOr(props, "Locked", false)
- m.state.Accounts.PasswordMode = dbusutil.GetOr(props, "PasswordMode", int32(0))
-
- return nil
-}
-
-func (m *Manager) updateSettingsState() error {
- if !m.state.Settings.Available || m.settingsObj == nil {
- return fmt.Errorf("settings portal not available")
- }
-
- var variant dbus.Variant
- err := m.settingsObj.Call(dbusPortalSettingsInterface+".ReadOne", 0, "org.freedesktop.appearance", "color-scheme").Store(&variant)
- if err != nil {
- return err
- }
-
- if colorScheme, ok := dbusutil.As[uint32](variant); ok {
- m.stateMutex.Lock()
- m.state.Settings.ColorScheme = colorScheme
- m.stateMutex.Unlock()
- }
-
- return nil
-}
-
-func (m *Manager) getAccountProperties(ctx context.Context) (map[string]dbus.Variant, error) {
- var props map[string]dbus.Variant
- err := m.accountsObj.CallWithContext(ctx, dbusPropsInterface+".GetAll", 0, dbusAccountsUserInterface).Store(&props)
- if err != nil {
- return nil, err
- }
- return props, nil
-}
-
-func (m *Manager) GetState() FreedeskState {
- m.stateMutex.RLock()
- defer m.stateMutex.RUnlock()
- return *m.state
-}
-
-func (m *Manager) Subscribe(id string) chan FreedeskState {
- ch := make(chan FreedeskState, 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() {
- state := m.GetState()
- m.subscribers.Range(func(key string, ch chan FreedeskState) bool {
- select {
- case ch <- state:
- default:
- }
- return true
- })
-}
-
-func (m *Manager) Close() {
- m.subscribers.Range(func(key string, ch chan FreedeskState) bool {
- close(ch)
- m.subscribers.Delete(key)
- return true
- })
-
- m.screensaverSubscribers.Range(func(key string, ch chan ScreensaverState) bool {
- close(ch)
- m.screensaverSubscribers.Delete(key)
- return true
- })
-
- if m.systemConn != nil {
- m.systemConn.Close()
- }
- if m.sessionConn != nil {
- m.sessionConn.Close()
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager_test.go
deleted file mode 100644
index b3617f5..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/manager_test.go
+++ /dev/null
@@ -1,143 +0,0 @@
-package freedesktop
-
-import (
- "sync"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestManager_GetState(t *testing.T) {
- state := &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- UserName: "testuser",
- RealName: "Test User",
- UID: 1000,
- },
- Settings: SettingsState{
- Available: true,
- ColorScheme: 1,
- },
- }
-
- manager := &Manager{
- state: state,
- stateMutex: sync.RWMutex{},
- }
-
- result := manager.GetState()
- assert.True(t, result.Accounts.Available)
- assert.Equal(t, "testuser", result.Accounts.UserName)
- assert.Equal(t, "Test User", result.Accounts.RealName)
- assert.Equal(t, uint64(1000), result.Accounts.UID)
- assert.True(t, result.Settings.Available)
- assert.Equal(t, uint32(1), result.Settings.ColorScheme)
-}
-
-func TestManager_GetState_ThreadSafe(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- UserName: "testuser",
- },
- Settings: SettingsState{
- Available: true,
- ColorScheme: 1,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- done := make(chan bool)
- for i := 0; i < 10; i++ {
- go func() {
- state := manager.GetState()
- assert.True(t, state.Accounts.Available)
- assert.Equal(t, "testuser", state.Accounts.UserName)
- done <- true
- }()
- }
-
- for i := 0; i < 10; i++ {
- <-done
- }
-}
-
-func TestManager_Close(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- systemConn: nil,
- sessionConn: nil,
- }
-
- assert.NotPanics(t, func() {
- manager.Close()
- })
-}
-
-func TestNewManager(t *testing.T) {
- t.Run("attempts to create manager", func(t *testing.T) {
- manager, err := NewManager()
- if err != nil {
- assert.Nil(t, manager)
- } else {
- assert.NotNil(t, manager)
- assert.NotNil(t, manager.state)
- assert.NotNil(t, manager.systemConn)
-
- manager.Close()
- }
- })
-}
-
-func TestManager_GetState_EmptyState(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{},
- stateMutex: sync.RWMutex{},
- }
-
- result := manager.GetState()
- assert.False(t, result.Accounts.Available)
- assert.Empty(t, result.Accounts.UserName)
- assert.False(t, result.Settings.Available)
- assert.Equal(t, uint32(0), result.Settings.ColorScheme)
-}
-
-func TestManager_AccountsState_Modification(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Accounts: AccountsState{
- Available: true,
- UserName: "testuser",
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- state := manager.GetState()
- state.Accounts.UserName = "modifieduser"
-
- original := manager.GetState()
- assert.Equal(t, "testuser", original.Accounts.UserName)
-}
-
-func TestManager_SettingsState_Modification(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Settings: SettingsState{
- Available: true,
- ColorScheme: 0,
- },
- },
- stateMutex: sync.RWMutex{},
- }
-
- state := manager.GetState()
- state.Settings.ColorScheme = 1
-
- original := manager.GetState()
- assert.Equal(t, uint32(0), original.Settings.ColorScheme)
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver.go
deleted file mode 100644
index 095a4c0..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver.go
+++ /dev/null
@@ -1,349 +0,0 @@
-package freedesktop
-
-import (
- "fmt"
- "path/filepath"
- "strings"
- "sync/atomic"
- "time"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/log"
- "github.com/godbus/dbus/v5"
- "github.com/godbus/dbus/v5/introspect"
-)
-
-type screensaverHandler struct {
- manager *Manager
-}
-
-func screensaverIntrospectIface(ifaceName string) introspect.Interface {
- return introspect.Interface{
- Name: ifaceName,
- Methods: []introspect.Method{
- {
- Name: "Inhibit",
- Args: []introspect.Arg{
- {Name: "application_name", Type: "s", Direction: "in"},
- {Name: "reason_for_inhibit", Type: "s", Direction: "in"},
- {Name: "cookie", Type: "u", Direction: "out"},
- },
- },
- {
- Name: "UnInhibit",
- Args: []introspect.Arg{
- {Name: "cookie", Type: "u", Direction: "in"},
- },
- },
- {
- Name: "GetActive",
- Args: []introspect.Arg{
- {Name: "active", Type: "b", Direction: "out"},
- },
- },
- {
- Name: "SetActive",
- Args: []introspect.Arg{
- {Name: "active", Type: "b", Direction: "in"},
- },
- },
- {
- Name: "Lock",
- },
- },
- Signals: []introspect.Signal{
- {
- Name: "ActiveChanged",
- Args: []introspect.Arg{
- {Name: "new_value", Type: "b"},
- },
- },
- },
- }
-}
-
-func (m *Manager) initializeScreensaver() error {
- if m.sessionConn == nil {
- m.stateMutex.Lock()
- m.state.Screensaver.Available = false
- m.stateMutex.Unlock()
- return nil
- }
-
- handler := &screensaverHandler{manager: m}
-
- m.screensaverFreedesktopClaimed = m.claimScreensaverName(handler,
- dbusScreensaverName, dbusScreensaverInterface, dbusScreensaverPath, dbusScreensaverPath2)
- m.screensaverGnomeClaimed = m.claimScreensaverName(handler,
- dbusGnomeScreensaverName, dbusGnomeScreensaverInterface, dbusGnomeScreensaverPath)
-
- if !m.screensaverFreedesktopClaimed && !m.screensaverGnomeClaimed {
- log.Warn("No screensaver interface could be claimed")
- m.stateMutex.Lock()
- m.state.Screensaver.Available = false
- m.stateMutex.Unlock()
- return nil
- }
-
- go m.watchPeerDisconnects()
-
- m.stateMutex.Lock()
- m.state.Screensaver.Available = true
- m.state.Screensaver.Active = false
- m.state.Screensaver.Inhibited = false
- m.state.Screensaver.Inhibitors = []ScreensaverInhibitor{}
- m.stateMutex.Unlock()
-
- log.Info("Screensaver listener initialized")
- return nil
-}
-
-func (m *Manager) claimScreensaverName(handler *screensaverHandler, name, iface string, paths ...dbus.ObjectPath) bool {
- reply, err := m.sessionConn.RequestName(name, dbus.NameFlagDoNotQueue)
- if err != nil {
- log.Warnf("Failed to request screensaver name %s: %v", name, err)
- return false
- }
- if reply != dbus.RequestNameReplyPrimaryOwner {
- log.Warnf("Screensaver name %s already owned by another process", name)
- return false
- }
- if err := m.exportScreensaverOnPaths(handler, iface, paths...); err != nil {
- log.Warnf("Failed to export screensaver on %s: %v", name, err)
- return false
- }
- log.Infof("Claimed %s on session bus", name)
- return true
-}
-
-// exportScreensaverOnPaths exports the handler and introspection on the given
-// paths under the specified interface name.
-func (m *Manager) exportScreensaverOnPaths(handler *screensaverHandler, ifaceName string, paths ...dbus.ObjectPath) error {
- iface := screensaverIntrospectIface(ifaceName)
- for _, path := range paths {
- if err := m.sessionConn.Export(handler, path, ifaceName); err != nil {
- return fmt.Errorf("export handler on %s: %w", path, err)
- }
- node := &introspect.Node{
- Name: string(path),
- Interfaces: []introspect.Interface{
- introspect.IntrospectData,
- iface,
- },
- }
- if err := m.sessionConn.Export(introspect.NewIntrospectable(node), path, "org.freedesktop.DBus.Introspectable"); err != nil {
- log.Warnf("Failed to export introspectable on %s: %v", path, err)
- }
- }
- return nil
-}
-
-func (h *screensaverHandler) Inhibit(sender dbus.Sender, appName, reason string) (uint32, *dbus.Error) {
- if appName == "" {
- return 0, dbus.NewError("org.freedesktop.DBus.Error.InvalidArgs", []any{"application name required"})
- }
-
- if reason == "" {
- return 0, dbus.NewError("org.freedesktop.DBus.Error.InvalidArgs", []any{"reason required"})
- }
-
- if strings.Contains(strings.ToLower(reason), "audio") && !strings.Contains(strings.ToLower(reason), "video") {
- log.Debugf("Ignoring audio-only inhibit from %s: %s", appName, reason)
- return 0, nil
- }
-
- if idx := strings.LastIndex(appName, "/"); idx != -1 && idx < len(appName)-1 {
- appName = appName[idx+1:]
- }
- appName = filepath.Base(appName)
-
- cookie := atomic.AddUint32(&h.manager.screensaverCookieCounter, 1)
-
- inhibitor := ScreensaverInhibitor{
- Cookie: cookie,
- AppName: appName,
- Reason: reason,
- Peer: string(sender),
- StartTime: time.Now().Unix(),
- }
-
- h.manager.stateMutex.Lock()
- h.manager.state.Screensaver.Inhibitors = append(h.manager.state.Screensaver.Inhibitors, inhibitor)
- h.manager.state.Screensaver.Inhibited = len(h.manager.state.Screensaver.Inhibitors) > 0
- h.manager.stateMutex.Unlock()
-
- log.Infof("Screensaver inhibited by %s (%s): %s -> cookie %08X", appName, sender, reason, cookie)
-
- h.manager.NotifyScreensaverSubscribers()
-
- return cookie, nil
-}
-
-func (h *screensaverHandler) UnInhibit(sender dbus.Sender, cookie uint32) *dbus.Error {
- h.manager.stateMutex.Lock()
- defer h.manager.stateMutex.Unlock()
-
- found := false
- inhibitors := h.manager.state.Screensaver.Inhibitors
- for i, inh := range inhibitors {
- if inh.Cookie != cookie {
- continue
- }
- log.Infof("Screensaver uninhibited by %s (%s) cookie %08X", inh.AppName, sender, cookie)
- h.manager.state.Screensaver.Inhibitors = append(inhibitors[:i], inhibitors[i+1:]...)
- found = true
- break
- }
-
- if !found {
- log.Debugf("UnInhibit: no match for cookie %08X", cookie)
- return nil
- }
-
- h.manager.state.Screensaver.Inhibited = len(h.manager.state.Screensaver.Inhibitors) > 0
-
- go h.manager.NotifyScreensaverSubscribers()
-
- return nil
-}
-
-func (m *Manager) watchPeerDisconnects() {
- if m.sessionConn == nil {
- return
- }
-
- if err := m.sessionConn.AddMatchSignal(
- dbus.WithMatchInterface("org.freedesktop.DBus"),
- dbus.WithMatchMember("NameOwnerChanged"),
- ); err != nil {
- log.Warnf("Failed to watch peer disconnects: %v", err)
- return
- }
-
- signals := make(chan *dbus.Signal, 64)
- m.sessionConn.Signal(signals)
-
- for sig := range signals {
- if sig.Name != "org.freedesktop.DBus.NameOwnerChanged" {
- continue
- }
- if len(sig.Body) < 3 {
- continue
- }
-
- name, ok1 := sig.Body[0].(string)
- newOwner, ok2 := sig.Body[2].(string)
- if !ok1 || !ok2 {
- continue
- }
- if newOwner != "" {
- continue
- }
-
- m.removeInhibitorsByPeer(name)
- }
-}
-
-func (m *Manager) removeInhibitorsByPeer(peer string) {
- m.stateMutex.Lock()
- defer m.stateMutex.Unlock()
-
- var remaining []ScreensaverInhibitor
- var removed []ScreensaverInhibitor
- for _, inh := range m.state.Screensaver.Inhibitors {
- if inh.Peer == peer {
- removed = append(removed, inh)
- continue
- }
- remaining = append(remaining, inh)
- }
-
- if len(removed) == 0 {
- return
- }
-
- for _, inh := range removed {
- log.Infof("Screensaver: peer %s died, removing inhibitor from %s (cookie %08X)", peer, inh.AppName, inh.Cookie)
- }
-
- m.state.Screensaver.Inhibitors = remaining
- m.state.Screensaver.Inhibited = len(remaining) > 0
-
- go m.NotifyScreensaverSubscribers()
-}
-
-func (m *Manager) GetScreensaverState() ScreensaverState {
- m.stateMutex.RLock()
- defer m.stateMutex.RUnlock()
- return m.state.Screensaver
-}
-
-func (m *Manager) SubscribeScreensaver(id string) chan ScreensaverState {
- ch := make(chan ScreensaverState, 64)
- m.screensaverSubscribers.Store(id, ch)
- return ch
-}
-
-func (m *Manager) UnsubscribeScreensaver(id string) {
- if val, ok := m.screensaverSubscribers.LoadAndDelete(id); ok {
- close(val)
- }
-}
-
-func (m *Manager) NotifyScreensaverSubscribers() {
- state := m.GetScreensaverState()
- m.screensaverSubscribers.Range(func(key string, ch chan ScreensaverState) bool {
- select {
- case ch <- state:
- default:
- }
- return true
- })
-}
-
-func (h *screensaverHandler) GetActive() (bool, *dbus.Error) {
- h.manager.stateMutex.RLock()
- active := h.manager.state.Screensaver.Active
- h.manager.stateMutex.RUnlock()
- return active, nil
-}
-
-func (h *screensaverHandler) SetActive(active bool) *dbus.Error {
- h.manager.SetScreenLockActive(active)
- return nil
-}
-
-func (h *screensaverHandler) Lock() *dbus.Error {
- h.manager.SetScreenLockActive(true)
- return nil
-}
-
-func (m *Manager) SetScreenLockActive(active bool) {
- m.stateMutex.Lock()
- changed := m.state.Screensaver.Active != active
- m.state.Screensaver.Active = active
- m.stateMutex.Unlock()
-
- if !changed {
- return
- }
-
- log.Infof("Screen lock active changed: %v", active)
- defer m.NotifyScreensaverSubscribers()
-
- if m.sessionConn == nil {
- return
- }
- if m.screensaverFreedesktopClaimed {
- if err := m.sessionConn.Emit(dbusScreensaverPath, dbusScreensaverInterface+".ActiveChanged", active); err != nil {
- log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusScreensaverPath, err)
- }
- if err := m.sessionConn.Emit(dbusScreensaverPath2, dbusScreensaverInterface+".ActiveChanged", active); err != nil {
- log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusScreensaverPath2, err)
- }
- }
- if m.screensaverGnomeClaimed {
- if err := m.sessionConn.Emit(dbusGnomeScreensaverPath, dbusGnomeScreensaverInterface+".ActiveChanged", active); err != nil {
- log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusGnomeScreensaverPath, err)
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver_test.go
deleted file mode 100644
index 324c17e..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/screensaver_test.go
+++ /dev/null
@@ -1,102 +0,0 @@
-package freedesktop
-
-import (
- "sync"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestSetScreenLockActive_ChangesState(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Screensaver: ScreensaverState{Available: true},
- },
- stateMutex: sync.RWMutex{},
- }
-
- assert.False(t, manager.GetScreensaverState().Active)
-
- manager.SetScreenLockActive(true)
- assert.True(t, manager.GetScreensaverState().Active)
-
- manager.SetScreenLockActive(false)
- assert.False(t, manager.GetScreensaverState().Active)
-}
-
-func TestSetScreenLockActive_NoChangeNoDuplicate(t *testing.T) {
- ch := make(chan ScreensaverState, 64)
- manager := &Manager{
- state: &FreedeskState{
- Screensaver: ScreensaverState{Available: true, Active: false},
- },
- stateMutex: sync.RWMutex{},
- }
- manager.screensaverSubscribers.Store("test", ch)
- defer manager.screensaverSubscribers.Delete("test")
-
- // Setting to same value should not notify
- manager.SetScreenLockActive(false)
-
- select {
- case <-ch:
- t.Fatal("should not have received notification for no-change")
- case <-time.After(50 * time.Millisecond):
- // Expected: no notification
- }
-}
-
-func TestSetScreenLockActive_NotifiesSubscribers(t *testing.T) {
- ch := make(chan ScreensaverState, 64)
- manager := &Manager{
- state: &FreedeskState{
- Screensaver: ScreensaverState{Available: true, Active: false},
- },
- stateMutex: sync.RWMutex{},
- }
- manager.screensaverSubscribers.Store("test", ch)
- defer manager.screensaverSubscribers.Delete("test")
-
- manager.SetScreenLockActive(true)
-
- select {
- case state := <-ch:
- assert.True(t, state.Active)
- case <-time.After(time.Second):
- t.Fatal("timeout waiting for subscriber notification")
- }
-}
-
-func TestSetScreenLockActive_NilSessionConn(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Screensaver: ScreensaverState{Available: true},
- },
- stateMutex: sync.RWMutex{},
- }
-
- assert.NotPanics(t, func() {
- manager.SetScreenLockActive(true)
- })
- assert.True(t, manager.GetScreensaverState().Active)
-}
-
-func TestGetActive_ReturnsCurrentState(t *testing.T) {
- manager := &Manager{
- state: &FreedeskState{
- Screensaver: ScreensaverState{Available: true, Active: true},
- },
- stateMutex: sync.RWMutex{},
- }
-
- handler := &screensaverHandler{manager: manager}
- active, dbusErr := handler.GetActive()
- assert.Nil(t, dbusErr)
- assert.True(t, active)
-}
-
-func TestScreensaverState_ActiveDefaultsFalse(t *testing.T) {
- state := ScreensaverState{}
- assert.False(t, state.Active)
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types.go
deleted file mode 100644
index 0a9517a..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package freedesktop
-
-import (
- "sync"
-
- "github.com/AvengeMedia/DankMaterialShell/core/pkg/syncmap"
- "github.com/godbus/dbus/v5"
-)
-
-type AccountsState struct {
- Available bool `json:"available"`
- UserPath string `json:"userPath"`
- IconFile string `json:"iconFile"`
- RealName string `json:"realName"`
- UserName string `json:"userName"`
- AccountType int32 `json:"accountType"`
- HomeDirectory string `json:"homeDirectory"`
- Shell string `json:"shell"`
- Email string `json:"email"`
- Language string `json:"language"`
- Location string `json:"location"`
- Locked bool `json:"locked"`
- PasswordMode int32 `json:"passwordMode"`
- UID uint64 `json:"uid"`
-}
-
-type SettingsState struct {
- Available bool `json:"available"`
- ColorScheme uint32 `json:"colorScheme"`
-}
-
-type ScreensaverInhibitor struct {
- Cookie uint32 `json:"cookie"`
- AppName string `json:"appName"`
- Reason string `json:"reason"`
- Peer string `json:"peer"`
- StartTime int64 `json:"startTime"`
-}
-
-type ScreensaverState struct {
- Available bool `json:"available"`
- Active bool `json:"active"`
- Inhibited bool `json:"inhibited"`
- Inhibitors []ScreensaverInhibitor `json:"inhibitors"`
-}
-
-type FreedeskState struct {
- Accounts AccountsState `json:"accounts"`
- Settings SettingsState `json:"settings"`
- Screensaver ScreensaverState `json:"screensaver"`
-}
-
-type Manager struct {
- state *FreedeskState
- stateMutex sync.RWMutex
- systemConn *dbus.Conn
- sessionConn *dbus.Conn
- accountsObj dbus.BusObject
- settingsObj dbus.BusObject
- currentUID uint64
- subscribers syncmap.Map[string, chan FreedeskState]
- screensaverSubscribers syncmap.Map[string, chan ScreensaverState]
- screensaverCookieCounter uint32
- screensaverFreedesktopClaimed bool
- screensaverGnomeClaimed bool
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types_test.go
deleted file mode 100644
index deb0327..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/freedesktop/types_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package freedesktop
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestAccountsState_Struct(t *testing.T) {
- state := AccountsState{
- Available: true,
- UserPath: "/org/freedesktop/Accounts/User1000",
- RealName: "Test User",
- UserName: "testuser",
- Locked: false,
- UID: 1000,
- }
-
- assert.True(t, state.Available)
- assert.Equal(t, "/org/freedesktop/Accounts/User1000", state.UserPath)
- assert.Equal(t, "Test User", state.RealName)
- assert.Equal(t, "testuser", state.UserName)
- assert.Equal(t, uint64(1000), state.UID)
- assert.False(t, state.Locked)
-}
-
-func TestSettingsState_Struct(t *testing.T) {
- state := SettingsState{
- Available: true,
- ColorScheme: 1, // Dark mode
- }
-
- assert.True(t, state.Available)
- assert.Equal(t, uint32(1), state.ColorScheme)
-}
-
-func TestFreedeskState_Struct(t *testing.T) {
- state := FreedeskState{
- Accounts: AccountsState{
- Available: true,
- UserName: "testuser",
- UID: 1000,
- },
- Settings: SettingsState{
- Available: true,
- ColorScheme: 0, // Light mode
- },
- }
-
- assert.True(t, state.Accounts.Available)
- assert.Equal(t, "testuser", state.Accounts.UserName)
- assert.True(t, state.Settings.Available)
- assert.Equal(t, uint32(0), state.Settings.ColorScheme)
-}
-
-func TestAccountsState_DefaultValues(t *testing.T) {
- state := AccountsState{}
-
- assert.False(t, state.Available)
- assert.Empty(t, state.UserPath)
- assert.Empty(t, state.UserName)
- assert.Equal(t, uint64(0), state.UID)
-}
-
-func TestSettingsState_DefaultValues(t *testing.T) {
- state := SettingsState{}
-
- assert.False(t, state.Available)
- assert.Equal(t, uint32(0), state.ColorScheme)
-}