mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
157 lines
2.9 KiB
Go
157 lines
2.9 KiB
Go
package screenshot
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strconv"
|
|
"syscall"
|
|
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
|
"github.com/godbus/dbus/v5"
|
|
)
|
|
|
|
const (
|
|
notifyDest = "org.freedesktop.Notifications"
|
|
notifyPath = "/org/freedesktop/Notifications"
|
|
notifyInterface = "org.freedesktop.Notifications"
|
|
)
|
|
|
|
type NotifyResult struct {
|
|
FilePath string
|
|
Clipboard bool
|
|
}
|
|
|
|
func SendNotification(result NotifyResult) {
|
|
conn, err := dbus.SessionBus()
|
|
if err != nil {
|
|
log.Debug("dbus session failed", "err", err)
|
|
return
|
|
}
|
|
|
|
var actions []string
|
|
if !result.Clipboard && result.FilePath != "" {
|
|
actions = []string{"default", "Open"}
|
|
}
|
|
|
|
hints := map[string]dbus.Variant{}
|
|
if result.FilePath != "" && !result.Clipboard {
|
|
hints["image-path"] = dbus.MakeVariant(result.FilePath)
|
|
}
|
|
|
|
summary := "Screenshot captured"
|
|
body := ""
|
|
if result.Clipboard {
|
|
body = "Copied to clipboard"
|
|
} else {
|
|
body = filepath.Base(result.FilePath)
|
|
}
|
|
|
|
obj := conn.Object(notifyDest, notifyPath)
|
|
call := obj.Call(
|
|
notifyInterface+".Notify",
|
|
0,
|
|
"DMS",
|
|
uint32(0),
|
|
"",
|
|
summary,
|
|
body,
|
|
actions,
|
|
hints,
|
|
int32(5000),
|
|
)
|
|
|
|
if call.Err != nil {
|
|
log.Debug("notify call failed", "err", call.Err)
|
|
return
|
|
}
|
|
|
|
var notificationID uint32
|
|
if err := call.Store(¬ificationID); err != nil {
|
|
log.Debug("failed to get notification id", "err", err)
|
|
return
|
|
}
|
|
|
|
if len(actions) == 0 || result.FilePath == "" {
|
|
return
|
|
}
|
|
|
|
spawnActionListener(notificationID, result.FilePath)
|
|
}
|
|
|
|
func spawnActionListener(notificationID uint32, filePath string) {
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
log.Debug("failed to get executable", "err", err)
|
|
return
|
|
}
|
|
|
|
cmd := exec.Command(exe, "notify-action", fmt.Sprintf("%d", notificationID), filePath)
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
Setsid: true,
|
|
}
|
|
cmd.Start()
|
|
}
|
|
|
|
func RunNotifyActionListener(args []string) {
|
|
if len(args) < 2 {
|
|
return
|
|
}
|
|
|
|
notificationID, err := strconv.ParseUint(args[0], 10, 32)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
filePath := args[1]
|
|
|
|
conn, err := dbus.SessionBus()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if err := conn.AddMatchSignal(
|
|
dbus.WithMatchObjectPath(notifyPath),
|
|
dbus.WithMatchInterface(notifyInterface),
|
|
); err != nil {
|
|
return
|
|
}
|
|
|
|
signals := make(chan *dbus.Signal, 10)
|
|
conn.Signal(signals)
|
|
|
|
for sig := range signals {
|
|
switch sig.Name {
|
|
case notifyInterface + ".ActionInvoked":
|
|
if len(sig.Body) < 2 {
|
|
continue
|
|
}
|
|
id, ok := sig.Body[0].(uint32)
|
|
if !ok || id != uint32(notificationID) {
|
|
continue
|
|
}
|
|
openFile(filePath)
|
|
return
|
|
|
|
case notifyInterface + ".NotificationClosed":
|
|
if len(sig.Body) < 1 {
|
|
continue
|
|
}
|
|
id, ok := sig.Body[0].(uint32)
|
|
if !ok || id != uint32(notificationID) {
|
|
continue
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func openFile(filePath string) {
|
|
cmd := exec.Command("xdg-open", filePath)
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
Setsid: true,
|
|
}
|
|
cmd.Start()
|
|
}
|