resolve conflicts

This commit is contained in:
piotr 2021-09-23 00:25:35 +02:00
parent c974593f77
commit 5fcc6239b6
4 changed files with 132 additions and 54 deletions

Binary file not shown.

127
main.go
View File

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/signal"
"path"
"path/filepath"
"strconv"
"strings"
@ -20,16 +21,16 @@ import (
"github.com/gotk3/gotk3/gtk"
)
const version = "0.1.12"
const version = "0.2.0"
var (
appDirs []string
configDirectory string
pinnedFile string
pinned []string
src glib.SourceHandle
id2entry map[string]desktopEntry
preferredApps map[string]interface{}
//src glib.SourceHandle
id2entry map[string]desktopEntry
preferredApps map[string]interface{}
)
var categoryNames = [...]string{
@ -82,6 +83,7 @@ var desktopEntries []desktopEntry
// UI elements
var (
win *gtk.Window
resultWindow *gtk.ScrolledWindow
fileSearchResults []string
searchEntry *gtk.SearchEntry
@ -98,6 +100,7 @@ var (
statusLabel *gtk.Label
status string
ignore string
showWindowTrigger bool
)
func defaultStringIfBlank(s, fallback string) string {
@ -125,45 +128,74 @@ var term = flag.String("term", defaultStringIfBlank(os.Getenv("TERM"), "alacritt
var nameLimit = flag.Int("fslen", 80, "File Search name length Limit")
var noCats = flag.Bool("nocats", false, "Disable filtering by category")
var noFS = flag.Bool("nofs", false, "Disable file search")
var resident = flag.Bool("r", false, "Leave the program resident in memory")
var debug = flag.Bool("d", false, "Turn on debug messages")
func main() {
timeStart := time.Now()
flag.Parse()
if *debug {
log.SetLevel(log.DebugLevel)
}
if *displayVersion {
fmt.Printf("nwg-drawer version %s\n", version)
os.Exit(0)
}
// 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 {
log.Info("SIGTERM received, bye bye!")
switch s {
case syscall.SIGTERM:
log.Debug("SIGTERM received, bye bye")
gtk.MainQuit()
case syscall.SIGUSR1:
if *resident {
// 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.
log.Debug("SIGUSR1 received, showing the window")
showWindowTrigger = true
} else {
log.Debug("SIGUSR1 received, and I'm not resident, bye bye")
gtk.MainQuit()
}
default:
log.Info("Unknown signal")
}
}
}()
// We want the same key/mouse binding to turn the dock off: kill the running instance and exit.
lockFilePath := fmt.Sprintf("%s/nwg-drawer.lock", tempDir())
// If running instance found and running residently, we want it to refresh and show the window.
// Otherwise we want the same command to terminate the drawer: kill the running instance and exit.
//lockFilePath := fmt.Sprintf("%s/nwg-drawer.lock", tempDir())
lockFilePath := path.Join(tempDir(), "nwg-drawer.lock")
lockFile, err := singleinstance.CreateLockFile(lockFilePath)
if err != nil {
pid, err := readTextFile(lockFilePath)
if err == nil {
i, err := strconv.Atoi(pid)
if err == nil {
log.Info("Running instance found, sending SIGTERM and exiting...")
syscall.Kill(i, syscall.SIGTERM)
if *resident {
log.Warnf("Resident instance already running (PID %v)", i)
} else {
log.Infof("Showing resident instance (PID %v)", i)
syscall.Kill(i, syscall.SIGUSR1)
}
}
}
os.Exit(0)
}
defer lockFile.Close()
log.Infof("term: %s", *term)
// LANGUAGE
if *lang == "" && os.Getenv("LANG") != "" {
*lang = strings.Split(os.Getenv("LANG"), ".")[0]
@ -226,7 +258,7 @@ 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)
}
@ -275,7 +307,11 @@ func main() {
searchEntry.GrabFocus()
searchEntry.SetText("")
} else {
gtk.MainQuit()
if !*resident {
gtk.MainQuit()
} else {
restoreStateAndHide()
}
}
return false
case gdk.KEY_downarrow, gdk.KEY_Up, gdk.KEY_Down, gdk.KEY_Left, gdk.KEY_Right, gdk.KEY_Tab,
@ -290,18 +326,6 @@ func main() {
}
})
// Close the window on leave, but not immediately, to avoid accidental closes
win.Connect("leave-notify-event", func() {
src = glib.TimeoutAdd(uint(500), func() bool {
gtk.MainQuit()
return false
})
})
win.Connect("enter-notify-event", func() {
cancelClose()
})
/*
In case someone REALLY needed to use X11 - for some stupid Zoom meeting or something, this allows
the drawer to behave properly on Openbox, and possibly somewhere else. For sure not on i3.
@ -341,13 +365,17 @@ func main() {
resultWindow, _ = gtk.ScrolledWindowNew(nil, nil)
resultWindow.SetEvents(int(gdk.ALL_EVENTS_MASK))
resultWindow.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
resultWindow.Connect("enter-notify-event", func() {
/*resultWindow.Connect("enter-notify-event", func() {
cancelClose()
})
})*/
resultWindow.Connect("button-release-event", func(sw *gtk.ScrolledWindow, e *gdk.Event) bool {
btnEvent := gdk.EventButtonNewFromEvent(e)
if btnEvent.Button() == 1 || btnEvent.Button() == 3 {
gtk.MainQuit()
if !*resident {
gtk.MainQuit()
} else {
restoreStateAndHide()
}
return true
}
return false
@ -392,6 +420,7 @@ func main() {
statusLineWrapper.PackStart(statusLabel, true, false, 0)
win.ShowAll()
if !*noFS {
fileSearchResultWrapper.SetSizeRequest(appFlowBox.GetAllocatedWidth(), 1)
fileSearchResultWrapper.Hide()
@ -399,8 +428,50 @@ func main() {
if !*noCats {
categoriesWrapper.SetSizeRequest(1, categoriesWrapper.GetAllocatedHeight()*2)
}
if *resident {
win.Hide()
}
t := time.Now()
log.Info(fmt.Sprintf("UI created in %v ms. Thank you for your patience.", t.Sub(timeStart).Milliseconds()))
// Check if showing the window has been requested (SIGUSR1)
glib.TimeoutAdd(uint(1), func() bool {
if showWindowTrigger && win != nil && !win.IsVisible() {
win.ShowAll()
// focus 1st element
b := appFlowBox.GetChildAtIndex(0)
if b != nil {
button, err := b.GetChild()
if err == nil {
button.ToWidget().GrabFocus()
}
}
}
showWindowTrigger = false
return true
})
gtk.Main()
}
func restoreStateAndHide() {
timeStart1 := time.Now()
win.Hide()
// 1. clear search
searchEntry.SetText("")
// 2. clear category filter (in gotk3 it means: rebuild, as we have no filtering here)
appFlowBox = setUpAppsFlowBox(nil, "")
for _, btn := range catButtons {
btn.SetImagePosition(gtk.POS_LEFT)
btn.SetSizeRequest(0, 0)
}
// 3. scroll to the top
resultWindow.GetVAdjustment().SetValue(0)
t := time.Now()
log.Debugf(fmt.Sprintf("UI hidden and restored in the backgroud in %v ms", t.Sub(timeStart1).Milliseconds()))
}

View File

@ -19,7 +19,6 @@ import (
log "github.com/sirupsen/logrus"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
"github.com/joshuarubin/go-sway"
)
@ -34,12 +33,12 @@ We might have left the window by accident, so let's clear the timeout if window
Furthermore - hovering a widget triggers window leave-notify-event event, and the timeout
needs to be cleared as well.
*/
func cancelClose() {
/*func cancelClose() {
if src > 0 {
glib.SourceRemove(src)
src = 0
}
}
}*/
func createPixbuf(icon string, size int) (*gdk.Pixbuf, error) {
iconTheme, err := gtk.IconThemeGetDefault()
@ -563,12 +562,20 @@ func launch(command string, terminal bool) {
msg := fmt.Sprintf("env vars: %s; command: '%s'; args: %s\n", envVars, elements[cmdIdx], elements[1+cmdIdx:])
log.Info(msg)
go cmd.Run()
cmd.Start()
if *resident {
restoreStateAndHide()
} else {
gtk.MainQuit()
}
/*go cmd.Run()
glib.TimeoutAdd(uint(150), func() bool {
gtk.MainQuit()
return false
})
})*/
}
func open(filePath string, xdgOpen bool) {
@ -586,10 +593,15 @@ func open(filePath string, xdgOpen bool) {
} else {
cmd = exec.Command(*fileManager, filePath)
}
fmt.Printf("Executing: %s", cmd)
log.Infof("Executing: %s", cmd)
cmd.Start()
gtk.MainQuit()
if *resident {
restoreStateAndHide()
} else {
gtk.MainQuit()
}
}
// Returns map output name -> gdk.Monitor

View File

@ -7,6 +7,7 @@ import (
"strings"
log "github.com/sirupsen/logrus"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)
@ -34,19 +35,13 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
btn, _ := gtk.ButtonNew()
var pixbuf *gdk.Pixbuf
var img *gtk.Image
var err error
if entry.Icon != "" {
pixbuf, err = createPixbuf(entry.Icon, *iconSize)
pixbuf, _ := createPixbuf(entry.Icon, *iconSize)
img, _ = gtk.ImageNewFromPixbuf(pixbuf)
} else {
pixbuf, err = createPixbuf("image-missing", *iconSize)
img, _ = gtk.ImageNewFromIconName("image-missing", gtk.ICON_SIZE_INVALID)
}
if err != nil {
log.Error(err)
pixbuf, _ = createPixbuf("unknown", *iconSize)
}
img, _ = gtk.ImageNewFromPixbuf(pixbuf)
btn.SetImage(img)
btn.SetAlwaysShowImage(true)
@ -92,11 +87,11 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
item.(*gtk.Widget).SetCanFocus(false)
})
}
flowBox.Connect("enter-notify-event", func() {
/*flowBox.Connect("enter-notify-event", func() {
cancelClose()
})
})*/
flowBox.ShowAll()
//flowBox.ShowAll()
return flowBox
}
@ -115,9 +110,9 @@ func setUpCategoriesButtonBox() *gtk.EventBox {
}
eventBox, _ := gtk.EventBoxNew()
eventBox.Connect("enter-notify-event", func() {
/*eventBox.Connect("enter-notify-event", func() {
cancelClose()
})
})*/
hBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
eventBox.Add(hBox)
button, _ := gtk.ButtonNewWithLabel("All")
@ -246,6 +241,7 @@ func flowBoxButton(entry desktopEntry) *gtk.Button {
if entry.Icon != "" {
pixbuf, err = createPixbuf(entry.Icon, *iconSize)
} else {
log.Warnf("Undefined icon for %s", entry.Name)
pixbuf, err = createPixbuf("image-missing", *iconSize)
}
if err != nil {
@ -295,9 +291,9 @@ func setUpFileSearchResultContainer() *gtk.FlowBox {
}
flowBox, _ := gtk.FlowBoxNew()
flowBox.SetProperty("orientation", gtk.ORIENTATION_VERTICAL)
flowBox.Connect("enter-notify-event", func() {
/*flowBox.Connect("enter-notify-event", func() {
cancelClose()
})
})*/
fileSearchResultWrapper.PackStart(flowBox, false, false, 10)
return flowBox
@ -323,9 +319,9 @@ func walk(path string, d fs.DirEntry, e error) error {
func setUpSearchEntry() *gtk.SearchEntry {
searchEntry, _ := gtk.SearchEntryNew()
searchEntry.SetPlaceholderText("Type to search")
searchEntry.Connect("enter-notify-event", func() {
/*searchEntry.Connect("enter-notify-event", func() {
cancelClose()
})
})*/
searchEntry.Connect("search-changed", func() {
for _, btn := range catButtons {
btn.SetImagePosition(gtk.POS_LEFT)
@ -380,7 +376,6 @@ func setUpSearchEntry() *gtk.SearchEntry {
if w == nil && fileSearchResultFlowBox != nil {
f := fileSearchResultFlowBox.GetChildAtIndex(0)
if f != nil {
//f.SetCanFocus(false)
button, err := f.GetChild()
if err == nil {
button.ToWidget().SetCanFocus(true)