guix_mirror_bot pushed a commit to branch master
in repository guix.
commit bd380757db78a29b5f3dc0f8aece740ee9cd8257
Author: Sughosha <[email protected]>
AuthorDate: Fri Mar 27 18:07:34 2026 +0530
gnu: Add nwg-dock.
* gnu/packages/nwg-shell.scm (nwg-dock): New variable.
* gnu/packages/patches/nwg-dock-0.4.3-fallback-paths.patch: New file.
* gnu/local.mk (dist_patch_DATA): Register it.
Relates-to: guix/guix!7644
Reviewed-by: Maxim Cournoyer <[email protected]>
Signed-off-by: Sharlatan Hellseher <[email protected]>
---
gnu/local.mk | 1 +
gnu/packages/nwg-shell.scm | 71 +++++++
.../patches/nwg-dock-0.4.3-fallback-paths.patch | 230 +++++++++++++++++++++
3 files changed, 302 insertions(+)
diff --git a/gnu/local.mk b/gnu/local.mk
index 1cd3a50598..bc8edc9ac5 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -2019,6 +2019,7 @@ dist_patch_DATA =
\
%D%/packages/patches/nvi-assume-preserve-path.patch \
%D%/packages/patches/nvi-dbpagesize-binpower.patch \
%D%/packages/patches/nvi-db4.patch \
+ %D%/packages/patches/nwg-dock-0.4.3-fallback-paths.patch \
%D%/packages/patches/nwg-drawer-0.7.5-fallback-paths.patch \
%D%/packages/patches/obs-advanced-masks-nlohmann-json.patch \
%D%/packages/patches/obs-modules-location.patch \
diff --git a/gnu/packages/nwg-shell.scm b/gnu/packages/nwg-shell.scm
index 1f74f8c8e2..78c29cd307 100644
--- a/gnu/packages/nwg-shell.scm
+++ b/gnu/packages/nwg-shell.scm
@@ -928,3 +928,74 @@ from the need to manually edit configuration files.
This application is a part of the nwg-shell project.")
(license license:expat)))
+
+(define-public nwg-dock
+ (package
+ (name "nwg-dock")
+ (version "0.4.3")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/nwg-piotr/nwg-dock")
+ (commit (string-append "v" version))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "1gagfm2igbwdsi9f4gs7lmvqjmxvdp0zkm6yl9b0qi7wjnb3hsb2"))
+ (patches
+ (search-patches "nwg-dock-0.4.3-fallback-paths.patch"))))
+ (build-system go-build-system)
+ (arguments
+ (list
+ ;; XXX: nwg-dock/tools.go:980:15: github.com/sirupsen/logrus.Errorf call
+ ;; has arguments but no formatting directives
+ #:tests? #f
+ #:install-source? #f
+ #:import-path "github.com/nwg-piotr/nwg-dock"
+ #:phases
+ #~(modify-phases %standard-phases
+ (add-after 'unpack 'patch-paths
+ (lambda _
+ (with-directory-excursion "src/github.com/nwg-piotr/nwg-dock"
+ (substitute* '("main.go" "tools.go")
+ (("\\/usr\\/share") (string-append #$output "/share"))))))
+ (add-after 'install 'install-data
+ (lambda _
+ (mkdir-p (string-append #$output "/share"))
+ (with-directory-excursion (string-append "src/github.com/"
+ "nwg-piotr/nwg-dock")
+ (copy-recursively "config"
+ (string-append #$output "/share/nwg-dock"))
+ (copy-recursively "images"
+ (string-append #$output
+ "/share/nwg-dock/images"))
+ (install-file "README.md"
+ (string-append #$output
+ "/share/doc/nwg-dock")))))
+ (add-after 'install 'wrap-program
+ (lambda _
+ (wrap-program (string-append #$output "/bin/nwg-dock")
+ `("GI_TYPELIB_PATH" =
+ (,(getenv "GI_TYPELIB_PATH")))))))))
+ (native-inputs
+ (list gobject-introspection
+ go-github-com-allan-simon-go-singleinstance
+ go-github-com-dlasky-gotk3-layershell
+ go-github-com-gotk3-gotk3
+ go-github-com-joshuarubin-go-sway
+ go-github-com-sirupsen-logrus
+ pkg-config))
+ (inputs
+ (list bash-minimal
+ gtk+
+ gtk-layer-shell))
+ (home-page "https://nwg-piotr.github.io/nwg-shell/nwg-dock")
+ (synopsis "GTK3 based dock for sway")
+ (description
+ "nwg-dock is a fully configurable (w/ command line arguments and CSS) GTK3
+based dock, written in Go, aimed exclusively at sway Wayland compositor. It
+features pinned buttons, task buttons, the workspace switcher and the launcher
+button.
+
+This application is a part of the nwg-shell project.")
+ (license license:expat)))
diff --git a/gnu/packages/patches/nwg-dock-0.4.3-fallback-paths.patch
b/gnu/packages/patches/nwg-dock-0.4.3-fallback-paths.patch
new file mode 100644
index 0000000000..daa20e1d06
--- /dev/null
+++ b/gnu/packages/patches/nwg-dock-0.4.3-fallback-paths.patch
@@ -0,0 +1,230 @@
+https://github.com/nwg-piotr/nwg-dock/pull/59
+
+From 1c4cc6924e052e9c3227e21ff97000b2a3aad7f1 Mon Sep 17 00:00:00 2001
+From: Sughosha <[email protected]>
+Date: Fri, 10 Apr 2026 10:50:59 +0530
+Subject: [PATCH] Support fallback paths
+
+---
+ main.go | 32 +++++++++++++++++----
+ tools.go | 88 +++++++++++++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 95 insertions(+), 25 deletions(-)
+
+diff --git a/main.go b/main.go
+index 1fd943b..705ff9f 100644
+--- a/main.go
++++ b/main.go
+@@ -48,6 +48,9 @@ var (
+ windowStateChannel chan WindowState = make(chan
WindowState, 1)
+ detectorEnteredAt int64
+ appIdsToIgnore []string
++ currentWsNumIcon string
++ activeWorkspaceIcon string
++ cssFilePath string
+ )
+
+ // Flags
+@@ -180,8 +183,14 @@ func buildMainBox(tasks []task, vbox *gtk.Box) {
+ if e != nil {
+ return
+ }
+- wsPixbuf, e :=
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
fmt.Sprintf("nwg-dock/images/%v.svg", currentWsNum)),
+- imgSizeScaled, imgSizeScaled)
++ if pathExists(filepath.Join(dataHome,
fmt.Sprintf("nwg-dock/images/%v.svg", currentWsNum))) {
++ currentWsNumIcon = filepath.Join(dataHome,
fmt.Sprintf("nwg-dock/images/%v.svg", currentWsNum))
++ } else if
pathExists(fmt.Sprintf("/usr/local/share/nwg-dock/images/%v.svg",
currentWsNum)) {
++ currentWsNumIcon =
fmt.Sprintf("/usr/local/share/nwg-dock/images/%v.svg", currentWsNum)
++ } else {
++ currentWsNumIcon =
fmt.Sprintf("/usr/share/nwg-dock/images/%v.svg", currentWsNum)
++ }
++ wsPixbuf, e := gdk.PixbufNewFromFileAtSize(currentWsNumIcon,
imgSizeScaled, imgSizeScaled)
+ if e == nil {
+ wsImage, _ := gtk.ImageNewFromPixbuf(wsPixbuf)
+ wsButton.SetImage(wsImage)
+@@ -195,8 +204,14 @@ func buildMainBox(tasks []task, vbox *gtk.Box) {
+ targetWsNum = activeWorkspace
+
+ glib.TimeoutAdd(0, func() bool {
+- wsPixbuf, e =
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
fmt.Sprintf("nwg-dock/images/%v.svg", activeWorkspace)),
+- imgSizeScaled,
imgSizeScaled)
++ if
pathExists(filepath.Join(dataHome, fmt.Sprintf("nwg-dock/images/%v.svg",
activeWorkspace))) {
++ activeWorkspaceIcon =
filepath.Join(dataHome, fmt.Sprintf("nwg-dock/images/%v.svg", activeWorkspace))
++ } else if
pathExists(fmt.Sprintf("/usr/local/share/nwg-dock/images/%v.svg",
activeWorkspace)) {
++ activeWorkspaceIcon =
fmt.Sprintf("/usr/local/share/nwg-dock/images/%v.svg", activeWorkspace)
++ } else {
++ activeWorkspaceIcon =
fmt.Sprintf("/usr/share/nwg-dock/images/%v.svg", activeWorkspace)
++ }
++ wsPixbuf, e =
gdk.PixbufNewFromFileAtSize(activeWorkspaceIcon, imgSizeScaled, imgSizeScaled)
+
+ if e == nil {
+ wsImage, _ =
gtk.ImageNewFromPixbuf(wsPixbuf)
+@@ -442,7 +457,14 @@ func main() {
+ createDir(configDirectory)
+
+ if !pathExists(fmt.Sprintf("%s/style.css", configDirectory)) {
+- err := copyFile(filepath.Join(dataHome, "nwg-dock/style.css"),
fmt.Sprintf("%s/style.css", configDirectory))
++ if pathExists(filepath.Join(dataHome, "nwg-dock/style.css")) {
++ cssFilePath = filepath.Join(dataHome,
"nwg-dock/style.css")
++ } else if pathExists("/usr/local/share/nwg-dock/style.css"){
++ cssFilePath = "/usr/local/share/nwg-dock/style.css"
++ } else {
++ cssFilePath = "/usr/share/nwg-dock/style.css"
++ }
++ err := copyFile(cssFilePath, fmt.Sprintf("%s/style.css",
configDirectory))
+ if err != nil {
+ log.Warnf("Error copying file: %s", err)
+ }
+diff --git a/tools.go b/tools.go
+index 0ef7c3a..e7cfbc4 100644
+--- a/tools.go
++++ b/tools.go
+@@ -24,6 +24,15 @@ import (
+
+ var descendants []sway.Node
+
++// Icons
++var (
++ iconIconMissing string
++ iconTaskEmpty string
++ iconGrid string
++ iconTaskSingle string
++ iconTaskMultiple string
++)
++
+ type task struct {
+ conID int64
+ ID string // will be created out of app_id or window class
+@@ -269,6 +278,15 @@ func workspaceNum(workspaces []sway.Workspace, name
string) int64 {
+ return 0
+ }
+
++func pathExists(name string) bool {
++ if _, err := os.Stat(name); err != nil {
++ if os.IsNotExist(err) {
++ return false
++ }
++ }
++ return true
++}
++
+ func pinnedButton(ID string) *gtk.Box {
+ box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
+ button, _ := gtk.ButtonNew()
+@@ -276,8 +294,14 @@ func pinnedButton(ID string) *gtk.Box {
+
+ image, err := createImage(ID, imgSizeScaled)
+ if err != nil {
+- pixbuf, err :=
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
"nwg-dock/images/icon-missing.svg"),
+- imgSizeScaled, imgSizeScaled)
++ if pathExists(filepath.Join(dataHome,
"nwg-dock/images/icon-missing.svg")) {
++ iconIconMissing = filepath.Join(dataHome,
"nwg-dock/images/icon-missing.svg")
++ } else if
pathExists("/usr/local/share/nwg-dock/images/icon-missing.svg") {
++ iconIconMissing =
"/usr/local/share/nwg-dock/images/icon-missing.svg"
++ } else {
++ iconIconMissing =
"/usr/share/nwg-dock/images/icon-missing.svg"
++ }
++ pixbuf, err := gdk.PixbufNewFromFileAtSize(iconIconMissing,
imgSizeScaled, imgSizeScaled)
+ if err == nil {
+ image, _ = gtk.ImageNewFromPixbuf(pixbuf)
+ } else {
+@@ -291,8 +315,14 @@ func pinnedButton(ID string) *gtk.Box {
+ button.SetAlwaysShowImage(true)
+ }
+ button.SetTooltipText(getName(ID))
+- pixbuf, _ := gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
"nwg-dock/images/task-empty.svg"),
+- imgSizeScaled, imgSizeScaled/8)
++ if pathExists(filepath.Join(dataHome,
"nwg-dock/images/task-empty.svg")) {
++ iconTaskEmpty = filepath.Join(dataHome,
"nwg-dock/images/task-empty.svg")
++ } else if pathExists("/usr/local/share/nwg-dock/images/task-empty.svg")
{
++ iconTaskEmpty =
"/usr/local/share/nwg-dock/images/task-empty.svg"
++ } else {
++ iconTaskEmpty = "/usr/share/nwg-dock/images/task-empty.svg"
++ }
++ pixbuf, _ := gdk.PixbufNewFromFileAtSize(iconTaskEmpty, imgSizeScaled,
imgSizeScaled/8)
+ img, _ := gtk.ImageNewFromPixbuf(pixbuf)
+ box.PackStart(img, false, false, 0)
+
+@@ -332,7 +362,15 @@ func pinnedMenuContext(taskID string) gtk.Menu {
+ func launcherButton() *gtk.Button {
+ if !*noLauncher && *launcherCmd != "" {
+ button, _ := gtk.ButtonNew()
+- pixbuf, err :=
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
"nwg-dock/images/grid.svg"), imgSizeScaled, imgSizeScaled)
++
++ if pathExists(filepath.Join(dataHome,
"nwg-dock/images/grid.svg")) {
++ iconGrid = filepath.Join(dataHome,
"nwg-dock/images/grid.svg")
++ } else if
pathExists("/usr/local/share/nwg-dock/images/grid.svg") {
++ iconGrid = "/usr/local/share/nwg-dock/images/grid.svg"
++ } else {
++ iconGrid = "/usr/share/nwg-dock/images/grid.svg"
++ }
++ pixbuf, err := gdk.PixbufNewFromFileAtSize(iconGrid,
imgSizeScaled, imgSizeScaled)
+ if err == nil {
+ image, _ := gtk.ImageNewFromPixbuf(pixbuf)
+ button.SetImage(image)
+@@ -382,8 +420,14 @@ func taskButton(t task, instances []task) *gtk.Box {
+
+ image, err := createImage(t.ID, imgSizeScaled)
+ if err != nil {
+- pixbuf, err :=
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
"nwg-dock/images/icon-missing.svg"),
+- imgSizeScaled, imgSizeScaled)
++ if pathExists(filepath.Join(dataHome,
"nwg-dock/images/icon-missing.svg")) {
++ iconIconMissing = filepath.Join(dataHome,
"nwg-dock/images/icon-missing.svg")
++ } else if
pathExists("/usr/local/share/nwg-dock/images/icon-missing.svg") {
++ iconIconMissing =
"/usr/local/share/nwg-dock/images/icon-missing.svg"
++ } else {
++ iconIconMissing =
"/usr/share/nwg-dock/images/icon-missing.svg"
++ }
++ pixbuf, err := gdk.PixbufNewFromFileAtSize(iconIconMissing,
imgSizeScaled, imgSizeScaled)
+ if err == nil {
+ image, _ = gtk.ImageNewFromPixbuf(pixbuf)
+ } else {
+@@ -398,13 +442,26 @@ func taskButton(t task, instances []task) *gtk.Box {
+ }
+ button.SetTooltipText(getName(t.ID))
+ var img *gtk.Image
++
+ if len(instances) < 2 {
+- pixbuf, _ :=
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
"nwg-dock/images/task-single.svg"),
+- imgSizeScaled, imgSizeScaled/8)
++ if pathExists(filepath.Join(dataHome,
"nwg-dock/images/task-single.svg")) {
++ iconTaskSingle = filepath.Join(dataHome,
"nwg-dock/images/task-single.svg")
++ } else if
pathExists("/usr/local/share/nwg-dock/images/task-single.svg") {
++ iconTaskSingle =
"/usr/local/share/nwg-dock/images/task-single.svg"
++ } else {
++ iconTaskSingle =
"/usr/share/nwg-dock/images/task-single.svg"
++ }
++ pixbuf, _ := gdk.PixbufNewFromFileAtSize(iconTaskSingle,
imgSizeScaled, imgSizeScaled/8)
+ img, _ = gtk.ImageNewFromPixbuf(pixbuf)
+ } else {
+- pixbuf, _ :=
gdk.PixbufNewFromFileAtSize(filepath.Join(dataHome,
"nwg-dock/images/task-multiple.svg"),
+- imgSizeScaled, imgSizeScaled/8)
++ if pathExists(filepath.Join(dataHome,
"nwg-dock/images/task-multiple.svg")) {
++ iconTaskMultiple = filepath.Join(dataHome,
"nwg-dock/images/task-multiple.svg")
++ } else if
pathExists("/usr/local/share/nwg-dock/images/task-multiple.svg") {
++ iconTaskMultiple =
"/usr/local/share/nwg-dock/images/task-multiple.svg"
++ } else {
++ iconTaskMultiple =
"/usr/share/nwg-dock/images/task-multiple.svg"
++ }
++ pixbuf, _ := gdk.PixbufNewFromFileAtSize(iconTaskMultiple,
imgSizeScaled, imgSizeScaled/8)
+ img, _ = gtk.ImageNewFromPixbuf(pixbuf)
+ }
+ box.PackStart(img, false, false, 0)
+@@ -875,15 +932,6 @@ func getName(appName string) string {
+ return name
+ }
+
+-func pathExists(name string) bool {
+- if _, err := os.Stat(name); err != nil {
+- if os.IsNotExist(err) {
+- return false
+- }
+- }
+- return true
+-}
+-
+ func loadTextFile(path string) ([]string, error) {
+ bytes, err := os.ReadFile(path)
+ if err != nil {
+--
+2.52.0
+