Skip to content

Commit

Permalink
Merge pull request #19 from nwg-piotr/backports
Browse files Browse the repository at this point in the history
run residently with IPC
  • Loading branch information
nwg-piotr committed Oct 5, 2021
2 parents 0dffbd5 + 44d7ae8 commit 8b480f5
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 34 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ get:
go get "github.com/sirupsen/logrus"

build:
go build -o bin/nwg-dock *.go
go build -o bin/nwg-dock .

install:
-pkill -f nwg-dock
sleep 1
mkdir -p /usr/share/nwg-dock
cp -r images /usr/share/nwg-dock
cp config/* /usr/share/nwg-dock
Expand All @@ -21,4 +23,4 @@ uninstall:
rm /usr/bin/nwg-dock

run:
go run *.go
go run .
45 changes: 33 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This program is a part of the [nwg-shell](https://github.com/nwg-piotr/nwg-shell

Fully configurable (w/ command line arguments and css) dock, written in Go, aimed exclusively at [sway](https://github.com/swaywm/sway) Wayland compositor. It features pinned buttons, task buttons, the workspace switcher and the launcher button. The latter by default starts [nwg-drawer](https://github.com/nwg-piotr/nwg-drawer) or `nwggrid` (application grid) - if found. In the picture(s) below the dock has been shown together with [nwg-panel](https://github.com/nwg-piotr/nwg-panel).

![06.png](https://scrot.cloud/images/2021/04/02/06.png)
![v020.png](https://scrot.cloud/images/2021/10/06/v020.png)

[more pictures](https://scrot.cloud/album/nwg-dock.BuZM)

Expand Down Expand Up @@ -38,32 +38,52 @@ Either start the dock permanently in the sway config file,
exec nwg-dock [arguments]
```

or assign the command to some key binding. Running the command again kills existing program instance, so that
or assign the command to some key binding. Running the command again kills the existing program instance, so that
you could use the same key to open and close the dock.

## Running in autohiDe mode
## Running the dock residently

If you run the program with the `-d` argument, it will start up hidden. Move the mouse pointer to expected dock
location for the dock to show up. It will be hidden a second after you leave the window or use a button. Invisible
hot spots to activate the dock will be created on all your outputs, unless you specify one with the `-o` argument.

As the dock in autohide mode is expected to be started from the sway config with
If you run the program with the `-d` or `-r` argument (preferably in autostart), it will start up hidden.

```text
exec_always nwg-dock -d
```

...re-execution of the command with the `-d` argument won't kill the running instance. If the dock is already
running, another instance will exit with 0 code. In case you'd like to terminate it anyway, just use the
`nwg-dock` command with no argument.
or

```text
exec_always nwg-dock -r
```

### `-d` for autohiDe

Move the mouse pointer to expected dock location for the dock to show up. It will be hidden a second after you leave the window. Invisible hot spots will be created on all your outputs, unless you specify one with the `-o` argument.

### `-r` for just Resident

No hotspot will be created. To show/hide the dock, bind the `exec nwg-dock` command to some key or button.
How about the `Menu` key, which is usually useless?

Re-execution of the same command hides the dock. If a resident instance found, the `nwg-dock` command w/o
arguments sends `SIGUSR1` to it. Actually `pkill -USR1 nwg-dock` could be used instead. This also works in autohiDe
mode.

Re-execution of the command with the `-d` or `-r` argument won't kill the running instance. If the dock is
running residently, another instance will just exit with 0 code. In case you'd like to terminate it anyway, you need to `pkill -f nwg-dock`.

*NOTE: you need to kill the running instance before reloading sway, if you've just changed the arguments you
auto-start the dock with.*

```txt
nwg-dock -h
Usage of nwg-dock:
-a string
Alignment in full width/height: "start", "center" or "end" (default "center")
-c string
Command assigned to the launcher button
-d auto-hiDe: show dock when hotspot hovered, close when left or a button clicked
-debug
turn on debug messages
-f take Full screen width/height
-i int
Icon size (default 48)
Expand All @@ -78,13 +98,14 @@ Usage of nwg-dock:
-mt int
Margin Top
-nolauncher
don't show launcher button switcher
don't show the launcher button
-nows
don't show the workspace switcher
-o string
name of Output to display the dock on
-p string
Position: "bottom", "top" or "left" (default "bottom")
-r Leave the program resident, but w/o hotspot
-s string
Styling: css file name (default "style.css")
-v display Version information
Expand Down
Binary file modified bin/nwg-dock
Binary file not shown.
81 changes: 66 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"github.com/gotk3/gotk3/gtk"
)

const version = "0.1.6"
const version = "0.2.0"

var (
appDirs []string
Expand All @@ -36,7 +36,9 @@ var (
widgetAnchor, menuAnchor gdk.Gravity
imgSizeScaled int
currentWsNum, targetWsNum int64
dockWindow *gtk.Window
win *gtk.Window
showWindowTrigger bool
hideWindowTrigger bool
)

// Flags
Expand All @@ -58,6 +60,7 @@ var marginRight = flag.Int("mr", 0, "Margin Right")
var marginBottom = flag.Int("mb", 0, "Margin Bottom")
var noWs = flag.Bool("nows", false, "don't show the workspace switcher")
var noLauncher = flag.Bool("nolauncher", false, "don't show the launcher button")
var resident = flag.Bool("r", false, "Leave the program resident, but w/o hotspot")
var debug = flag.Bool("debug", false, "turn on debug messages")

func buildMainBox(tasks []task, vbox *gtk.Box) {
Expand Down Expand Up @@ -197,7 +200,7 @@ func buildMainBox(tasks []task, vbox *gtk.Box) {
cmd := exec.Command(elements[0], elements[1:]...)
go cmd.Run()
if *autohide {
dockWindow.Hide()
win.Hide()
}
})
button.Connect("enter-notify-event", cancelClose)
Expand Down Expand Up @@ -263,38 +266,70 @@ func main() {
log.SetLevel(log.DebugLevel)
}

if *autohide && *resident {
log.Warn("autohiDe and Resident arguments are mutually exclusive, ignoring -d!")
*autohide = false
}

if *displayVersion {
fmt.Printf("nwg-dock version %s\n", version)
os.Exit(0)
}
if *autohide {
log.Info("Starting in autohiDe mode")
}
if *resident {
log.Info("Starting in resident mode")
}

// Gentle SIGTERM handler thanks to reiki4040 https://gist.github.com/reiki4040/be3705f307d3cd136e85
// v0.2: we also need to support SIGUSR from now on.
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGTERM)
signal.Notify(signalChan, syscall.SIGTERM, syscall.SIGUSR1)

go func() {
for {
s := <-signalChan
if s == syscall.SIGTERM {
switch s {
case syscall.SIGTERM:
log.Info("SIGTERM received, bye bye!")
gtk.MainQuit()
case syscall.SIGUSR1:
if *resident || *autohide {
// As win.Show() called from inside a goroutine randomly crashes GTK,
// let's just set e helper variable here. We'll be checking it with glib.TimeoutAdd.
if !win.IsVisible() {
log.Debug("SIGUSR1 received, showing the window")
showWindowTrigger = true
} else {
log.Debug("SIGUSR1 received, hiding the window")
hideWindowTrigger = true
}
} else {
log.Info("SIGUSR1 received, and I'm not resident, bye bye!")
gtk.MainQuit()
}
default:
log.Warn("Unknown signal")
}
}
}()

// Unless we are in autohide mode, we probably want the same key/mouse binding to turn the dock off.
// Kill the running instance and exit.
// Unless we are in autohide/resident mode, we probably want the same key/mouse binding to turn the dock off.
// Since v0.2 we can't just send SIGKILL if running instance found. We'll send SIGUSR1 instead.
// If it's running with `-r` or `-d` flag, it'll show the window. If not - it will die.
lockFilePath := fmt.Sprintf("%s/nwg-dock.lock", tempDir())
lockFile, err := singleinstance.CreateLockFile(lockFilePath)
if err != nil {
pid, err := readTextFile(lockFilePath)
if err == nil {
i, err := strconv.Atoi(pid)
if err == nil {
if !*autohide {
log.Info("Running instance found, sending SIGTERM and exiting...")
syscall.Kill(i, syscall.SIGTERM)
if *autohide || *resident {
log.Info("Running instance found, terminating...")
} else {
log.Info("Already running")
syscall.Kill(i, syscall.SIGUSR1)
log.Info("Sending SIGUSR1 to running instance and bye, bye!")
}
}
}
Expand Down Expand Up @@ -347,11 +382,10 @@ func main() {
gtk.AddProviderForScreen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
}

win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
win, err = gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
if err != nil {
log.Fatal("Unable to create window:", err)
}
dockWindow = win

layershell.InitForWindow(win)

Expand Down Expand Up @@ -431,7 +465,7 @@ func main() {

// Close the window on leave, but not immediately, to avoid accidental closes
win.Connect("leave-notify-event", func() {
if *autohide {
if *autohide || *resident {
src = glib.TimeoutAdd(uint(1000), func() bool {
win.Hide()
src = 0
Expand Down Expand Up @@ -479,7 +513,7 @@ func main() {
win.ShowAll()

if *autohide {
win.Hide()
glib.TimeoutAdd(uint(500), win.Hide)

mRefProvider, _ := gtk.CssProviderNew()
if err := mRefProvider.LoadFromPath(filepath.Join(dataHome, "nwg-dock/hotspot.css")); err != nil {
Expand Down Expand Up @@ -509,5 +543,22 @@ func main() {
}
}

if *resident {
glib.TimeoutAdd(uint(500), win.Hide)
}

glib.TimeoutAdd(uint(1), func() bool {
if showWindowTrigger && win != nil && !win.IsVisible() {
win.ShowAll()
showWindowTrigger = false
}
if hideWindowTrigger && win != nil && win.IsVisible() {
win.Hide()
hideWindowTrigger = false
}

return true
})

gtk.Main()
}
10 changes: 5 additions & 5 deletions tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ func launch(ID string) {
cmd.Start()

if *autohide {
dockWindow.Hide()
win.Hide()
}
}

Expand All @@ -849,7 +849,7 @@ func focusCon(conID int64) {

if *autohide {
src = glib.TimeoutAdd(uint(1000), func() bool {
dockWindow.Hide()
win.Hide()
return false
})
}
Expand All @@ -868,7 +868,7 @@ func focusWorkspace(num int64) {

if *autohide {
src = glib.TimeoutAdd(uint(1000), func() bool {
dockWindow.Hide()
win.Hide()
return false
})
}
Expand All @@ -887,7 +887,7 @@ func killCon(conID int64) {

if *autohide {
src = glib.TimeoutAdd(uint(1000), func() bool {
dockWindow.Hide()
win.Hide()
return false
})
}
Expand All @@ -907,7 +907,7 @@ func con2WS(conID int64, wsNum int) {

if *autohide {
src = glib.TimeoutAdd(uint(1000), func() bool {
dockWindow.Hide()
win.Hide()
return false
})
}
Expand Down

0 comments on commit 8b480f5

Please sign in to comment.