Repository: hajimehoshi/guigui
Pull request #112: Linux system theme detection
Author: login: temidaradev
Created: 2025-05-06T22:54:18Z | Merged: 2025-05-08T16:45:43Z

Cite: https://github.com/hajimehoshi/guigui/pull/98#issuecomment-2848814243
and used ChatGPT to format code.


https://github.com/user-attachments/assets/08578f28-0f92-41ac-8fe9-12ad90460f94







Diff:
diff --git a/internal/colormode/colormode_linux.go b/internal/colormode/colormode_linux.go
new file mode 100644
index 00000000..5e967802
--- /dev/null
+++ b/internal/colormode/colormode_linux.go
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	if mode := checkGSettings(); mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Unknown
+	}
+	if mode := checkGTKSettingsFile(filepath.Join(homeDir+".config", "gtk-4.0", "settings.ini")); mode != Unknown {
+		return mode
+	}
+
+	if mode := checkGTKSettingsFile(filepath.Join(homeDir+".config", "gtk-3.0", "settings.ini")); mode != Unknown {
+		return mode
+	}
+
+	return Unknown
+}
+
+func checkGSettings() ColorMode {
+	out, err := exec.Command("gsettings", "get", "org.gnome.desktop.interface", "color-scheme").Output()
+	if err != nil {
+		return Unknown
+	}
+
+	value := strings.TrimSpace(string(out))
+	value = strings.Trim(value, "'")
+
+	switch value {
+	case "prefer-dark":
+		return Dark
+	case "default", "prefer-light":
+		return Light
+	default:
+		return Unknown
+	}
+}
+
+func checkGTKSettingsFile(path string) ColorMode {
+	data, err := os.ReadFile(path)
+	if err != nil {
+		return Unknown
+	}
+
+	content := strings.ToLower(string(data))
+	if strings.Contains(content, "gtk-application-prefer-dark-theme=true") {
+		return Dark
+	}
+	return Light
+}
diff --git a/internal/colormode/colormode_others.go b/internal/colormode/colormode_others.go
index 53398f57..13a53e69 100644
--- a/internal/colormode/colormode_others.go
+++ b/internal/colormode/colormode_others.go
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-FileCopyrightText: 2025 The Guigui Authors
 
-//go:build !darwin && !js && !windows
+//go:build !darwin && !js && !linux && !windows
 
 package colormode
 


Reviews:
user: login: hajimehoshi
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-07T04:49:20Z
user: login: temidaradev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T06:34:57Z
user: login: hajimehoshi
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-07T06:35:46Z
user: login: temidaradev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T06:37:56Z
user: login: hajimehoshi
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-07T06:53:50Z
user: login: temidaradev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T06:56:17Z
user: login: hajimehoshi
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-07T18:53:59Z
user: login: temidaradev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T18:55:15Z
user: login: hajimehoshi
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-08T04:38:39Z
user: login: hajimehoshi
body: LGTM, thanks!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-08T16:44:58Z

Review comments:
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: Unknown
created_at: 2025-05-07T04:23:56Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
+	if mode != Unknown {
+		return mode
+	}
+
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-3.0/settings.ini")
+	if mode != Unknown {
+		return mode
+	}
+
+	return Light
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: Unknown
created_at: 2025-05-07T04:24:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: Use `filepath.Join`:

```go
filepath.Join(homeDir, ".config", "gtk-4.0", "settings.ini")
```
created_at: 2025-05-07T04:48:30Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
+	if mode != Unknown {
+		return mode
+	}
+
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-3.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: ditto
created_at: 2025-05-07T04:48:35Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
+	if mode != Unknown {
+		return mode
+	}
+
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-3.0/settings.ini")
+	if mode != Unknown {
+		return mode
+	}
+
+	return Light
+}
+
+func checkGSettings() ColorMode {
+	out, err := exec.Command("gsettings", "get", "org.gnome.desktop.interface", "color-scheme").Output()
+	if err != nil {
+		return Unknown
+	}
+
+	value := strings.TrimSpace(string(out))
+	value = strings.Trim(value, "'")
+
+	switch value {
+	case "prefer-dark":
+		return Dark
+	case "default", "prefer-light":
+		return Light
+	default:
+		return Unknown
+	}
+}
+
+func checkGtkSettingsFile(path string) ColorMode {
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: rename this to `checkGTKSettingsFile`
created_at: 2025-05-07T04:48:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: temidaradev
body: I think i should rewrite the checkGTKSettingsFile function with this.
created_at: 2025-05-07T06:34:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: What do you mean?
created_at: 2025-05-07T06:35:46Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: temidaradev
body: If i use filepath.Join as you send, checkGTKSettingsFile will no longer needed, I will handle it when Im at home 🙂
created_at: 2025-05-07T06:37:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: > If i use filepath.Join as you send, checkGTKSettingsFile will no longer needed, I will handle it when Im at home 🙂

I don't think so. `filepath.Join` just returns a string.
created_at: 2025-05-07T06:53:50Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: temidaradev
body: I will check at home, i dont have a laptop with me right now 😞
created_at: 2025-05-07T06:56:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: This is not fixed yet.
created_at: 2025-05-07T18:53:59Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Light
+	}
+	mode = checkGtkSettingsFile(homeDir + "/.config/gtk-4.0/settings.ini")
path: internal/colormode/colormode_linux.go
user: login: temidaradev
body: Ahh wait i forgot to separate 
created_at: 2025-05-07T18:55:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,66 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: Let's write this in one line.

```go
if mode := checkGSettings(); mode != Unknown {
    return mode
}
```
created_at: 2025-05-08T04:37:32Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,66 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Unknown
+	}
+	mode = checkGTKSettingsFile(filepath.Join(homeDir+".config", "gtk-4.0", "settings.ini"))
+	if mode != Unknown {
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: ditto
created_at: 2025-05-08T04:37:38Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,66 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Guigui Authors
+
+package colormode
+
+import (
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+)
+
+func systemColorMode() ColorMode {
+	mode := checkGSettings()
+	if mode != Unknown {
+		return mode
+	}
+
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		return Unknown
+	}
+	mode = checkGTKSettingsFile(filepath.Join(homeDir+".config", "gtk-4.0", "settings.ini"))
+	if mode != Unknown {
+		return mode
+	}
+
+	mode = checkGTKSettingsFile(filepath.Join(homeDir+".config", "gtk-3.0", "settings.ini"))
+	if mode != Unknown {
path: internal/colormode/colormode_linux.go
user: login: hajimehoshi
body: ditto
created_at: 2025-05-08T04:37:43Z
author_association: COLLABORATOR

PR comments:
user: login: temidaradev
created_at: 2025-05-07T06:33:54Z
body: Sorry for forgetting to use Light instead of Unknown in related places. 
author_association: CONTRIBUTOR
user: login: temidaradev
created_at: 2025-05-07T18:34:28Z
body: Renamed function and added filepath.Join you requested like this: ``mode = checkGTKSettingsFile(filepath.Join(homeDir + "/.config/gtk-4.0/settings.ini"))``
author_association: CONTRIBUTOR
user: login: hajimehoshi
created_at: 2025-05-07T18:55:06Z
body: > Renamed function and added filepath.Join you requested like this

Please read my comment carefully... `filepath.Join` with one argument doesn't make sense.
author_association: COLLABORATOR
user: login: temidaradev
created_at: 2025-05-07T18:59:03Z
body: okay fixed it: ``mode = checkGTKSettingsFile(filepath.Join(homeDir+".config", "gtk-4.0", "settings.ini"))``
im sorry for my careless mistake
author_association: CONTRIBUTOR
user: login: hajimehoshi
created_at: 2025-05-07T19:01:21Z
body: I'll take a look tomorrow.

As systemColorMode is called once per second, not using a process or reading files would be better, but probably this is better than nothing.
author_association: COLLABORATOR