33 Commits

Author SHA1 Message Date
piotr
c0eb0965a8 update README.md 2024-10-26 00:58:25 +02:00
piotr
c940139fd9 add default styling for #math-result label #134 2024-10-26 00:43:34 +02:00
piotr
10b1b2a1e6 Merge remote-tracking branch 'origin/main' 2024-10-26 00:38:44 +02:00
piotr
b4b7d3486a add CSS ID to math result label #134 2024-10-26 00:38:20 +02:00
Piotr Miller
61a5595d84 Merge pull request #132 from msmafra/main
Update README.md
2024-10-15 11:27:46 +02:00
Marcelo dos Santos Mafra
cb44c7215f Update README.md
nwg-drawer seems to look in its own folder ~/.config/nwg-drawer for preferred-apps.json and excluded-dirs and not nwg-panel's folder
2024-10-11 17:59:30 -03:00
piotr
e7fafebf55 bump to 0.5.2 2024-10-09 02:12:19 +02:00
piotr
702cbb1c5c update golang.org/x/sys 2024-10-09 02:07:51 +02:00
piotr
7de2854041 set gtk-layer-shell namespace 2024-10-09 02:06:30 +02:00
Piotr Miller
be6b71673d Merge pull request #131 from nwg-piotr/calc
add a simple calculator in the search box
2024-10-03 01:20:01 +02:00
piotr
9c48c585b7 add rounded corners 2024-10-03 01:10:35 +02:00
piotr
3977c4fc7c go -> 1.23 2024-10-03 01:05:14 +02:00
piotr
46a526ced8 close result win on btn release 2024-10-03 01:04:53 +02:00
piotr
12da77fbfc update README.md 2024-10-03 00:48:23 +02:00
piotr
484c6ccb29 add comments 2024-10-03 00:33:54 +02:00
piotr
7aac5a4f52 add expression calculator 2024-09-30 22:09:56 +02:00
Piotr Miller
44e4c95900 Merge pull request #130 from nwg-piotr/backports
Merge pull request #129 from nwg-piotr/main
2024-09-22 14:05:20 +02:00
Piotr Miller
86a3398bc3 Merge pull request #129 from nwg-piotr/main
A bunch of fixes
2024-09-22 14:04:33 +02:00
piotr
c4a268332a bump to 0.5.0 2024-09-22 13:57:01 +02:00
piotr
e77d189f4a println -> log.Debug 2024-09-22 13:54:32 +02:00
piotr
e3cb0af2bd println -> log.Debug 2024-09-22 13:51:46 +02:00
piotr
1015f4c48f fix hyprclt & mapping output->monitor 2024-09-22 13:44:02 +02:00
piotr
86c92328cd update dependencies 2024-09-22 13:29:07 +02:00
piotr
4afa9f1aa3 add riverctl spawn 2024-09-22 13:26:18 +02:00
Piotr Miller
0bce8cf971 Merge pull request #127 from mattkae/main
Update gotk3 to the latest version to avoid build failures
2024-08-11 22:20:16 +02:00
Matthew Kosarek
e6a1130524 Update gotk3 to the latest version to avoid build failures 2024-08-11 15:59:14 -04:00
Piotr Miller
433c05ca1e Merge pull request #125 from nwg-piotr/icon-theme
update README.md
2024-06-29 20:20:34 +02:00
piotr
cd06a981cb update README.md 2024-06-29 20:19:12 +02:00
Piotr Miller
0f6f92433e Merge pull request #124 from nwg-piotr/icon-theme
Add the `-pbuseicontheme` flagIcon theme
2024-06-29 03:01:20 +02:00
piotr
3ffd09b5d7 add more desc 2024-06-29 02:40:01 +02:00
piotr
071841da46 bump to 0.4.9 2024-06-29 02:38:43 +02:00
piotr
c7a0b564c0 improve description 2024-06-29 02:34:41 +02:00
piotr
6862711010 add pbUseIconTheme flag #122 2024-06-29 02:32:27 +02:00
7 changed files with 190 additions and 80 deletions

View File

@@ -101,9 +101,11 @@ Usage of nwg-drawer:
-pbreboot string -pbreboot string
command for the Reboot power bar icon command for the Reboot power bar icon
-pbsize int -pbsize int
power bar icon size (default 64) power bar icon size (only works w/ built-in icons) (default 64)
-pbsleep string -pbsleep string
command for the sleep power bar icon command for the sleep power bar icon
-pbuseicontheme
use icon theme instead of built-in icons in power bar
-r Leave the program resident in memory -r Leave the program resident in memory
-s string -s string
Styling: css file name (default "drawer.css") Styling: css file name (default "drawer.css")
@@ -170,7 +172,7 @@ Edit `~/.config/nwg-drawer/drawer.css` to your taste.
When the search phrase is at least 3 characters long, your XDG user directories are being searched. When the search phrase is at least 3 characters long, your XDG user directories are being searched.
Use the **left mouse button** to open a file with the `xdg-open` command. As configuring file associations for it is Use the **left mouse button** to open a file with the `xdg-open` command. As configuring file associations for it is
PITA, you may override them, by creating the `~/.config/nwg-panel/preferred-apps.json` file with your own definitions. PITA, you may override them, by creating the `~/.config/nwg-drawer/preferred-apps.json` file with your own definitions.
### Sample `preferred-apps.json` file content ### Sample `preferred-apps.json` file content
@@ -197,13 +199,29 @@ I've noy yet tried other file managers.
### File search exclusions ### File search exclusions
You may want to exclude some paths inside your XDG user directories from searching. If so, define exclusions in the You may want to exclude some paths inside your XDG user directories from searching. If so, define exclusions in the
`~/.config/nwg-panel/excluded-dirs` file, e.g. like this: `~/.config/nwg-drawer/excluded-dirs` file, e.g. like this:
```text ```text
# exclude all paths containing 'node_modules' # exclude all paths containing 'node_modules'
node_modules node_modules
``` ```
### Calculations in the search box
If the search box is not empty, and you press Enter, the search box content will be evaluated as an arithmetic operation.
If the result is not an error, it will be displayed in a small window, and copied to the clipboard with wl-copy.
Press any key to close the window.
You may change the result label styling e.g. like this:
```css
/* math operation result label */
#math-label {
font-weight: bold;
font-size: 16px
}
```
## Credits ## Credits
This program uses some great libraries: This program uses some great libraries:
@@ -215,3 +233,4 @@ Copyright (c) 2015-2018 gotk3 contributors
- [go-singleinstance](github.com/allan-simon/go-singleinstance) Copyright (c) 2015 Allan Simon - [go-singleinstance](github.com/allan-simon/go-singleinstance) Copyright (c) 2015 Allan Simon
- [logrus](https://github.com/sirupsen/logrus) Copyright (c) 2014 Simon Eskildsen - [logrus](https://github.com/sirupsen/logrus) Copyright (c) 2014 Simon Eskildsen
- [fsnotify](https://github.com/fsnotify/fsnotify) Copyright (c) 2012-2019 fsnotify Authors - [fsnotify](https://github.com/fsnotify/fsnotify) Copyright (c) 2012-2019 fsnotify Authors
- [expr](https://github.com/expr-lang/expr) Copyright (c) 2018 Anton Medvedev

View File

@@ -1,5 +1,5 @@
window { window {
background-color: rgba (36, 47, 79, 0.95); background-color: rgba(36, 47, 79, 0.95);
color: #eeeeee color: #eeeeee
} }
@@ -32,3 +32,9 @@ button:hover {
border: 1px dotted gray; border: 1px dotted gray;
border-radius: 15px border-radius: 15px
} }
/* math operation result label */
#math-label {
font-weight: bold;
font-size: 16px
}

9
go.mod
View File

@@ -1,19 +1,20 @@
module github.com/nwg-piotr/nwg-drawer module github.com/nwg-piotr/nwg-drawer
go 1.22 go 1.23
require ( require (
github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37 github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37
github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774 github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774
github.com/fsnotify/fsnotify v1.7.0 github.com/fsnotify/fsnotify v1.7.0
github.com/gotk3/gotk3 v0.6.3 github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56
github.com/joshuarubin/go-sway v1.2.0 github.com/joshuarubin/go-sway v1.2.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
) )
require ( require (
github.com/expr-lang/expr v1.16.9 // indirect
github.com/joshuarubin/lifecycle v1.1.4 // indirect github.com/joshuarubin/lifecycle v1.1.4 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sync v0.7.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.21.0 // indirect golang.org/x/sys v0.26.0 // indirect
) )

38
go.sum
View File

@@ -3,23 +3,15 @@ github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37/go.m
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlasky/gotk3-layershell v0.0.0-20221218201547-1f6674a3f872 h1:16qcNl+UgbvudN7wPv+zq4mmDSYJWdLv5jbVhS7+OVI=
github.com/dlasky/gotk3-layershell v0.0.0-20221218201547-1f6674a3f872/go.mod h1:JHLx2Wz4mAPVwn4PFhC69ydwyHP4A3wQvlg7HKVVc1U=
github.com/dlasky/gotk3-layershell v0.0.0-20230802002603-b0c42cd8474f h1:qDnUQAD7tVX/gnL6uSgouzfGNA4xXH+B/fd6Ko19GgM=
github.com/dlasky/gotk3-layershell v0.0.0-20230802002603-b0c42cd8474f/go.mod h1:JHLx2Wz4mAPVwn4PFhC69ydwyHP4A3wQvlg7HKVVc1U=
github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774 h1:o87OVL4olQBlVwN3+NSVQpS6gj9FWUYtxOfHXWZigUE= github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774 h1:o87OVL4olQBlVwN3+NSVQpS6gj9FWUYtxOfHXWZigUE=
github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774/go.mod h1:JHLx2Wz4mAPVwn4PFhC69ydwyHP4A3wQvlg7HKVVc1U= github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774/go.mod h1:JHLx2Wz4mAPVwn4PFhC69ydwyHP4A3wQvlg7HKVVc1U=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gotk3/gotk3 v0.6.1/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q= github.com/gotk3/gotk3 v0.6.1/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/gotk3/gotk3 v0.6.2 h1:sx/PjaKfKULJPTPq8p2kn2ZbcNFxpOJqi4VLzMbEOO8= github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56 h1:eR+xxC8qqKuPMTucZqaklBxLIT7/4L7dzhlwKMrDbj8=
github.com/gotk3/gotk3 v0.6.2/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q= github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/gotk3/gotk3 v0.6.3 h1:+Ke4WkM1TQUNOlM2TZH6szqknqo+zNbX3BZWVXjSHYw=
github.com/gotk3/gotk3 v0.6.3/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/gotk3/gotk3 v0.6.4 h1:5ur/PRr86PwCG8eSj98D1eXvhrNNK6GILS2zq779dCg=
github.com/gotk3/gotk3 v0.6.4/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/joshuarubin/go-sway v1.2.0 h1:t3eqW504//uj9PDwFf0+IVfkD+WoOGaDX5gYIe0BHyM= github.com/joshuarubin/go-sway v1.2.0 h1:t3eqW504//uj9PDwFf0+IVfkD+WoOGaDX5gYIe0BHyM=
github.com/joshuarubin/go-sway v1.2.0/go.mod h1:qcDd6f25vJ0++wICwA1BainIcRC67p2Mb4lsrZ0k3/k= github.com/joshuarubin/go-sway v1.2.0/go.mod h1:qcDd6f25vJ0++wICwA1BainIcRC67p2Mb4lsrZ0k3/k=
github.com/joshuarubin/lifecycle v1.0.0/go.mod h1:sRy++ATvR9Ee21tkRdFkQeywAWvDsue66V70K0Dnl54= github.com/joshuarubin/lifecycle v1.0.0/go.mod h1:sRy++ATvR9Ee21tkRdFkQeywAWvDsue66V70K0Dnl54=
@@ -38,26 +30,18 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

65
main.go
View File

@@ -3,6 +3,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/expr-lang/expr"
"os" "os"
"os/signal" "os/signal"
"path" "path"
@@ -21,7 +22,7 @@ import (
"github.com/gotk3/gotk3/gtk" "github.com/gotk3/gotk3/gtk"
) )
const version = "0.4.8" const version = "0.5.2"
var ( var (
appDirs []string appDirs []string
@@ -171,7 +172,7 @@ var itemSpacing = flag.Uint("spacing", 20, "icon spacing")
var lang = flag.String("lang", "", "force lang, e.g. \"en\", \"pl\"") var lang = flag.String("lang", "", "force lang, e.g. \"en\", \"pl\"")
var fileManager = flag.String("fm", "thunar", "File Manager") var fileManager = flag.String("fm", "thunar", "File Manager")
var term = flag.String("term", defaultTermIfBlank(os.Getenv("TERM"), "foot"), "Terminal emulator") var term = flag.String("term", defaultTermIfBlank(os.Getenv("TERM"), "foot"), "Terminal emulator")
var wm = flag.String("wm", "", "use swaymsg exec (with 'sway' argument) or hyprctl dispatch exec (with 'hyprland') to launch programs") var wm = flag.String("wm", "", "use swaymsg exec (with 'sway' argument) or hyprctl dispatch exec (with 'hyprland') or riverctl spawn (with 'river') to launch programs")
var nameLimit = flag.Int("fslen", 80, "File Search name LENgth Limit") var nameLimit = flag.Int("fslen", 80, "File Search name LENgth Limit")
var noCats = flag.Bool("nocats", false, "Disable filtering by category") var noCats = flag.Bool("nocats", false, "Disable filtering by category")
var noFS = flag.Bool("nofs", false, "Disable file search") var noFS = flag.Bool("nofs", false, "Disable file search")
@@ -181,7 +182,8 @@ var pbLock = flag.String("pblock", "", "command for the Lock power bar icon")
var pbPoweroff = flag.String("pbpoweroff", "", "command for the Poweroff power bar icon") var pbPoweroff = flag.String("pbpoweroff", "", "command for the Poweroff power bar icon")
var pbReboot = flag.String("pbreboot", "", "command for the Reboot power bar icon") var pbReboot = flag.String("pbreboot", "", "command for the Reboot power bar icon")
var pbSleep = flag.String("pbsleep", "", "command for the sleep power bar icon") var pbSleep = flag.String("pbsleep", "", "command for the sleep power bar icon")
var pbSize = flag.Int("pbsize", 64, "power bar icon size") var pbSize = flag.Int("pbsize", 64, "power bar icon size (only works w/ built-in icons)")
var pbUseIconTheme = flag.Bool("pbuseicontheme", false, "use icon theme instead of built-in icons in power bar")
var debug = flag.Bool("d", false, "Turn on Debug messages") var debug = flag.Bool("d", false, "Turn on Debug messages")
func main() { func main() {
@@ -418,7 +420,6 @@ func main() {
err = cssProvider.LoadFromPath(*cssFileName) err = cssProvider.LoadFromPath(*cssFileName)
if err != nil { if err != nil {
log.Errorf("ERROR: %s css file not found or erroneous. Using GTK styling.", *cssFileName) log.Errorf("ERROR: %s css file not found or erroneous. Using GTK styling.", *cssFileName)
log.Errorf("%s", err)
} else { } else {
log.Info(fmt.Sprintf("Using style from %s", *cssFileName)) log.Info(fmt.Sprintf("Using style from %s", *cssFileName))
screen, _ := gdk.ScreenGetDefault() screen, _ := gdk.ScreenGetDefault()
@@ -432,12 +433,13 @@ func main() {
if wayland() { if wayland() {
layershell.InitForWindow(win) layershell.InitForWindow(win)
layershell.SetNamespace(win, "nwg-drawer")
var output2mon map[string]*gdk.Monitor var output2mon map[string]*gdk.Monitor
if *targetOutput != "" { if *targetOutput != "" {
// We want to assign layershell to a monitor, but we only know the output name! // We want to assign layershell to a monitor, but we only know the output name!
output2mon, err = mapOutputs() output2mon, err = mapOutputs()
fmt.Println(">>>", output2mon) log.Debugf("output2mon: %s", output2mon)
if err == nil { if err == nil {
monitor := output2mon[*targetOutput] monitor := output2mon[*targetOutput]
layershell.SetMonitor(win, monitor) layershell.SetMonitor(win, monitor)
@@ -493,12 +495,26 @@ func main() {
} }
} }
return true return true
} else if key.KeyVal() == gdk.KEY_Tab { } else if key.KeyVal() == gdk.KEY_Tab {
if firstPowerBtn != nil { if firstPowerBtn != nil {
firstPowerBtn.ToWidget().GrabFocus() firstPowerBtn.ToWidget().GrabFocus()
} }
} else if key.KeyVal() == gdk.KEY_Return {
s, _ := searchEntry.GetText()
if s != "" {
// Check if the search box content is an arithmetic expression. If so, display the result
// and copy to the clipboard with wl-copy.
result, err := expr.Eval(s, nil)
if err == nil {
log.Debugf("Setting up mathemathical operation result window. Operation: %s, result: %v", s, result)
setUpOperationResultWindow(s, fmt.Sprintf("%v", result))
}
}
return true
} }
return false return true
}) })
win.Connect("key-press-event", func(_ *gtk.Window, event *gdk.Event) bool { win.Connect("key-press-event", func(_ *gtk.Window, event *gdk.Event) bool {
@@ -512,8 +528,8 @@ func main() {
if !searchEntry.IsFocus() { if !searchEntry.IsFocus() {
searchEntry.GrabFocusWithoutSelecting() searchEntry.GrabFocusWithoutSelecting()
} }
return false
} }
return false
}) })
/* /*
@@ -624,27 +640,52 @@ func main() {
powerBarWrapper.PackStart(powerButtonsWrapper, true, false, 12) powerBarWrapper.PackStart(powerButtonsWrapper, true, false, 12)
if *pbPoweroff != "" { if *pbPoweroff != "" {
btn := powerButton(filepath.Join(dataDirectory, "img/poweroff.svg"), *pbPoweroff) btn, _ := gtk.ButtonNew()
if !*pbUseIconTheme {
btn = powerButton(filepath.Join(dataDirectory, "img/poweroff.svg"), *pbPoweroff)
} else {
btn = powerButton("system-shutdown-symbolic", *pbPoweroff)
}
powerButtonsWrapper.PackEnd(btn, true, false, 0) powerButtonsWrapper.PackEnd(btn, true, false, 0)
firstPowerBtn = btn firstPowerBtn = btn
} }
if *pbSleep != "" { if *pbSleep != "" {
btn := powerButton(filepath.Join(dataDirectory, "img/sleep.svg"), *pbSleep) btn, _ := gtk.ButtonNew()
if !*pbUseIconTheme {
btn = powerButton(filepath.Join(dataDirectory, "img/sleep.svg"), *pbSleep)
} else {
btn = powerButton("face-yawn-symbolic", *pbSleep)
}
powerButtonsWrapper.PackEnd(btn, true, false, 0) powerButtonsWrapper.PackEnd(btn, true, false, 0)
firstPowerBtn = btn firstPowerBtn = btn
} }
if *pbReboot != "" { if *pbReboot != "" {
btn := powerButton(filepath.Join(dataDirectory, "img/reboot.svg"), *pbReboot) btn, _ := gtk.ButtonNew()
if !*pbUseIconTheme {
btn = powerButton(filepath.Join(dataDirectory, "img/reboot.svg"), *pbReboot)
} else {
btn = powerButton("system-reboot-symbolic", *pbReboot)
}
powerButtonsWrapper.PackEnd(btn, true, false, 0) powerButtonsWrapper.PackEnd(btn, true, false, 0)
firstPowerBtn = btn firstPowerBtn = btn
} }
if *pbExit != "" { if *pbExit != "" {
btn := powerButton(filepath.Join(dataDirectory, "img/exit.svg"), *pbExit) btn, _ := gtk.ButtonNew()
if !*pbUseIconTheme {
btn = powerButton(filepath.Join(dataDirectory, "img/exit.svg"), *pbExit)
} else {
btn = powerButton("system-log-out-symbolic", *pbExit)
}
powerButtonsWrapper.PackEnd(btn, true, false, 0) powerButtonsWrapper.PackEnd(btn, true, false, 0)
firstPowerBtn = btn firstPowerBtn = btn
} }
if *pbLock != "" { if *pbLock != "" {
btn := powerButton(filepath.Join(dataDirectory, "img/lock.svg"), *pbLock) btn, _ := gtk.ButtonNew()
if !*pbUseIconTheme {
btn = powerButton(filepath.Join(dataDirectory, "img/lock.svg"), *pbLock)
} else {
btn = powerButton("system-lock-screen-symbolic", *pbLock)
}
powerButtonsWrapper.PackEnd(btn, true, false, 0) powerButtonsWrapper.PackEnd(btn, true, false, 0)
firstPowerBtn = btn firstPowerBtn = btn
} }

View File

@@ -571,7 +571,7 @@ func savePinned() {
} }
} }
func launch(command string, terminal bool) { func launch(command string, terminal bool, terminate bool) {
// trim % and everything afterwards // trim % and everything afterwards
if strings.Contains(command, "%") { if strings.Contains(command, "%") {
cutAt := strings.Index(command, "%") cutAt := strings.Index(command, "%")
@@ -611,9 +611,11 @@ func launch(command string, terminal bool) {
cmd = exec.Command("swaymsg", "exec", strings.Join(elements, " ")) cmd = exec.Command("swaymsg", "exec", strings.Join(elements, " "))
} else if *wm == "hyprland" || *wm == "Hyprland" { } else if *wm == "hyprland" || *wm == "Hyprland" {
cmd = exec.Command("hyprctl", "dispatch", "exec", strings.Join(elements, " ")) cmd = exec.Command("hyprctl", "dispatch", "exec", strings.Join(elements, " "))
} else if *wm == "river" {
cmd = exec.Command("riverctl", "spawn", strings.Join(elements, " "))
} }
msg := fmt.Sprintf("command: %q; args: %q\n", cmd.Args[0], cmd.Args[1:]) msg := fmt.Sprintf("Executing command: %q; args: %q\n", cmd.Args[0], cmd.Args[1:])
log.Info(msg) log.Info(msg)
cmd.SysProcAttr = &syscall.SysProcAttr{ cmd.SysProcAttr = &syscall.SysProcAttr{
@@ -630,10 +632,12 @@ func launch(command string, terminal bool) {
}() }()
} }
if *resident { if terminate {
restoreStateAndHide() if *resident {
} else { restoreStateAndHide()
gtk.MainQuit() } else {
gtk.MainQuit()
}
} }
} }
@@ -687,13 +691,8 @@ func mapOutputs() (map[string]*gdk.Monitor, error) {
num := display.GetNMonitors() num := display.GetNMonitors()
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
mon, _ := display.GetMonitor(i) mon, _ := display.GetMonitor(i)
geometry := mon.GetGeometry() output := hyprlandMonitors[i]
// assign output to monitor on the basis of the same x, y coordinates result[output.Name] = mon
for _, output := range hyprlandMonitors {
if int(output.X) == geometry.GetX() && int(output.Y) == geometry.GetY() {
result[output.Name] = mon
}
}
} }
} else { } else {
return nil, err return nil, err
@@ -721,13 +720,8 @@ func mapOutputs() (map[string]*gdk.Monitor, error) {
num := display.GetNMonitors() num := display.GetNMonitors()
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
mon, _ := display.GetMonitor(i) mon, _ := display.GetMonitor(i)
geometry := mon.GetGeometry() output := outputs[i]
// assign output to monitor on the basis of the same x, y coordinates result[output.Name] = mon
for _, output := range outputs {
if int(output.Rect.X) == geometry.GetX() && int(output.Rect.Y) == geometry.GetY() {
result[output.Name] = mon
}
}
} }
} else { } else {
return nil, errors.New("output assignment only supported on sway and Hyprland") return nil, errors.New("output assignment only supported on sway and Hyprland")
@@ -754,7 +748,15 @@ func substring(s string, start int, end int) string {
func hyprctl(cmd string) ([]byte, error) { func hyprctl(cmd string) ([]byte, error) {
his := os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") his := os.Getenv("HYPRLAND_INSTANCE_SIGNATURE")
socketFile := fmt.Sprintf("/tmp/hypr/%s/.socket.sock", his) xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR")
hyprDir := ""
if xdgRuntimeDir != "" {
hyprDir = fmt.Sprintf("%s/hypr", xdgRuntimeDir)
} else {
hyprDir = "/tmp/hypr"
}
socketFile := fmt.Sprintf("%s/%s/.socket.sock", hyprDir, his)
conn, err := net.Dial("unix", socketFile) conn, err := net.Dial("unix", socketFile)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/dlasky/gotk3-layershell/layershell"
"io/fs" "io/fs"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -66,7 +67,7 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
btn.Connect("button-release-event", func(row *gtk.Button, e *gdk.Event) bool { btn.Connect("button-release-event", func(row *gtk.Button, e *gdk.Event) bool {
btnEvent := gdk.EventButtonNewFromEvent(e) btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 { if btnEvent.Button() == 1 {
launch(entry.Exec, entry.Terminal) launch(entry.Exec, entry.Terminal, true)
return true return true
} else if btnEvent.Button() == 3 { } else if btnEvent.Button() == 3 {
unpinItem(entry.DesktopID) unpinItem(entry.DesktopID)
@@ -75,7 +76,7 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
return false return false
}) })
btn.Connect("activate", func() { btn.Connect("activate", func() {
launch(entry.Exec, entry.Terminal) launch(entry.Exec, entry.Terminal, true)
}) })
btn.Connect("enter-notify-event", func() { btn.Connect("enter-notify-event", func() {
statusLabel.SetText(entry.CommentLoc) statusLabel.SetText(entry.CommentLoc)
@@ -274,7 +275,7 @@ func flowBoxButton(entry desktopEntry) *gtk.Button {
btnEvent := gdk.EventButtonNewFromEvent(e) btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 { if btnEvent.Button() == 1 {
if !beenScrolled { if !beenScrolled {
launch(exec, terminal) launch(exec, terminal, true)
return true return true
} }
} else if btnEvent.Button() == 3 { } else if btnEvent.Button() == 3 {
@@ -284,7 +285,7 @@ func flowBoxButton(entry desktopEntry) *gtk.Button {
return false return false
}) })
button.Connect("activate", func() { button.Connect("activate", func() {
launch(exec, terminal) launch(exec, terminal, true)
}) })
button.Connect("enter-notify-event", func() { button.Connect("enter-notify-event", func() {
statusLabel.SetText(desc) statusLabel.SetText(desc)
@@ -298,32 +299,37 @@ func flowBoxButton(entry desktopEntry) *gtk.Button {
return button return button
} }
func powerButton(iconPath, command string) *gtk.Button { func powerButton(iconPathOrName, command string) *gtk.Button {
button, _ := gtk.ButtonNew() button, _ := gtk.ButtonNew()
button.SetAlwaysShowImage(true) button.SetAlwaysShowImage(true)
var pixbuf *gdk.Pixbuf var pixbuf *gdk.Pixbuf
var img *gtk.Image var img *gtk.Image
var err error var err error
pixbuf, err = gdk.PixbufNewFromFileAtSize(iconPath, *pbSize, *pbSize) if !*pbUseIconTheme {
if err != nil { pixbuf, err = gdk.PixbufNewFromFileAtSize(iconPathOrName, *pbSize, *pbSize)
pixbuf, _ = createPixbuf("unknown", *pbSize) if err != nil {
log.Warnf("Couldn't find icon %s", iconPath) pixbuf, _ = createPixbuf("unknown", *pbSize)
log.Warnf("Couldn't find icon %s", iconPathOrName)
}
img, _ = gtk.ImageNewFromPixbuf(pixbuf)
} else {
img, _ = gtk.ImageNewFromIconName(iconPathOrName, gtk.ICON_SIZE_DIALOG)
} }
img, _ = gtk.ImageNewFromPixbuf(pixbuf)
button.SetImage(img) button.SetImage(img)
button.SetImagePosition(gtk.POS_TOP) button.SetImagePosition(gtk.POS_TOP)
button.Connect("button-release-event", func(btn *gtk.Button, e *gdk.Event) bool { button.Connect("button-release-event", func(btn *gtk.Button, e *gdk.Event) bool {
btnEvent := gdk.EventButtonNewFromEvent(e) btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 { if btnEvent.Button() == 1 {
launch(command, false) launch(command, false, true)
return true return true
} }
return false return false
}) })
button.Connect("activate", func() { button.Connect("activate", func() {
launch(command, false) launch(command, false, true)
}) })
button.Connect("enter-notify-event", func() { button.Connect("enter-notify-event", func() {
statusLabel.SetText(command) statusLabel.SetText(command)
@@ -579,3 +585,54 @@ func setUpUserFileSearchResultButton(fileName, filePath string) *gtk.Box {
box.PackStart(button, false, true, 0) box.PackStart(button, false, true, 0)
return box return box
} }
func setUpOperationResultWindow(operation string, result string) {
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
if err != nil {
log.Fatal("Unable to create result window:", err)
}
win.SetModal(true)
if wayland() {
layershell.InitForWindow(win)
layershell.SetLayer(win, layershell.LAYER_SHELL_LAYER_OVERLAY)
layershell.SetKeyboardMode(win, layershell.LAYER_SHELL_KEYBOARD_MODE_EXCLUSIVE)
}
// any key to close the window
win.Connect("key-release-event", func(_ *gtk.Window, event *gdk.Event) bool {
win.Destroy()
return true
})
// any button to close the window
win.Connect("button-release-event", func(_ *gtk.Window, event *gdk.Event) bool {
win.Destroy()
return true
})
outerVBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 6)
win.Add(outerVBox)
vBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 5)
outerVBox.PackStart(vBox, true, true, 6)
lbl, _ := gtk.LabelNew(fmt.Sprintf("%s = %s", operation, result))
lbl.SetProperty("name", "math-label")
vBox.PackStart(lbl, true, true, 12)
mRefProvider, _ := gtk.CssProviderNew()
css := "window { background-color: rgba (0, 0, 0, 255); color: #fff; border: solid 1px grey; border-radius: 5px}"
err = mRefProvider.LoadFromData(css)
if err != nil {
log.Warn(err)
}
ctx, _ := win.GetStyleContext()
ctx.AddProvider(mRefProvider, gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
win.ShowAll()
if wayland() {
cmd := fmt.Sprintf("wl-copy %v", result)
launch(cmd, false, false)
}
}