gtkmenu: Run application in terminal on CTRL+Enter

This commit is contained in:
Trevor Slocum 2019-08-28 21:24:45 -07:00
parent 3a492a6414
commit 34cc749965
4 changed files with 84 additions and 87 deletions

View File

@ -5,7 +5,13 @@
Desktop application launcher
## Installation
## Download
[**Download gmenu**](https://gmenu.rocketnine.space/download/) (Linux binaries are available)
## Compile
Note: This is only necessary if you did not download a binary.
### Console
@ -77,3 +83,7 @@ for_window [app_id="gmenu"] floating enable; resize set 745 105
```
bindsym $mod+d exec --no-startup-id gtkmenu
```
## Support
Please share suggestions/issues [here](https://todo.sr.ht/~tslocum/gmenu).

View File

@ -89,7 +89,7 @@ func updateEntryInfo() {
} else {
exLine = "bash -c "
if input != nil {
strings.TrimSpace(input.Buffer())
exLine += strings.TrimSpace(input.Buffer())
}
comLine = "Shell command"
@ -114,7 +114,10 @@ func listSelect() error {
waitUntilFinished = true
execute = input.Buffer()
} else if entry.Type == desktop.Application {
runInTerminal = entry.Terminal
if entry.Terminal {
runInTerminal = true
}
execute = entry.ExpandExec(shellquote.Join(flag.Args()...))
} else { // Type == desktop.Link
execute = shellquote.Join(config.BrowserCommand(), entry.URL)

View File

@ -27,11 +27,8 @@ const (
labelMarginTopComment = 4
)
var (
execLabel *gtk.Label
)
var execLabel *gtk.Label
// TODO: Load list item icon on show
func initList(container *gtk.Box) {
inputView = newTextView()
setNoExpand(&inputView.Widget)
@ -64,7 +61,7 @@ func initList(container *gtk.Box) {
listBox.SetFocusOnClick(false)
_, err = listBox.Connect("row-activated", func(_ *gtk.ListBox, _ *gtk.ListBoxRow) {
err := listSelect(inputView)
err := listSelect(inputView, false)
if err != nil {
log.Fatal(err)
}
@ -153,7 +150,6 @@ func initRow(container *gtk.Box, entry *gmenu.ListEntry, i int, lastEntry int) {
setNoExpand(&l.Widget)
initLabel(l)
//glib.IdleAdd(initLabel, l)
if !config.HideAppIcons && !config.HideAppDetails {
l.SetMarginTop(labelMarginTop)
@ -181,7 +177,6 @@ func initRow(container *gtk.Box, entry *gmenu.ListEntry, i int, lastEntry int) {
setNoExpand(&l.Widget)
initLabel(l)
//glib.IdleAdd(initLabel, l) // TODO Faster?
if !config.HideAppIcons {
l.SetMarginTop(labelMarginTopComment)
@ -231,24 +226,12 @@ func loadIconImage(img *gtk.Image, entry *gmenu.ListEntry) {
}
func updateList(input string) {
execLabel.SetText(input)
listBox.InvalidateFilter()
listBox.InvalidateSort()
execLabel.SetText(input)
var row *gtk.ListBoxRow
for i := 0; i < len(gmenu.Names); i++ {
row = listBox.GetRowAtIndex(i)
if row == nil {
return
} else if row.IsVisible() {
break
}
}
listBox.SelectRow(row)
inputView.GrabFocus()
listBox.SelectRow(listBox.GetRowAtIndex(0))
}
func newBox(orient gtk.Orientation) *gtk.Box {
@ -308,12 +291,11 @@ func selectedEntry() *desktop.Entry {
return gmenu.FilteredEntries[i].Entry
}
func listSelect(_ *gtk.TextView) error {
func listSelect(_ *gtk.TextView, runInTerminal bool) error {
gmenu.CloseInput()
var (
execute string
runInTerminal bool
waitUntilFinished bool
)
entry := selectedEntry()
@ -321,7 +303,10 @@ func listSelect(_ *gtk.TextView) error {
waitUntilFinished = true
execute = textViewText(inputView)
} else if entry.Type == desktop.Application {
runInTerminal = entry.Terminal
if entry.Terminal {
runInTerminal = true
}
execute = entry.ExpandExec(shellquote.Join(flag.Args()...))
} else { // Type == desktop.Link
execute = shellquote.Join(config.BrowserCommand(), entry.URL)
@ -353,20 +338,18 @@ func listSort(row1 *gtk.ListBoxRow, row2 *gtk.ListBoxRow, _ uintptr) int {
r1 := rowID(row1)
r2 := rowID(row2)
if r1 < 0 || r2 < 0 {
if r1 < 0 {
if gmenu.MatchEntry(r2) {
return 1
}
return -1
} else { // r2 < 0
if gmenu.MatchEntry(r1) {
return -1
}
if r1 < 0 {
if gmenu.MatchEntry(r2) {
return 1
}
return -1
} else if r2 < 0 {
if gmenu.MatchEntry(r1) {
return -1
}
return 1
}
if gmenu.Sort(r1, r2) {
@ -403,3 +386,48 @@ func fallbackIcon(entry *gmenu.ListEntry) string {
return "text-html"
}
func setupKeyBindings(w *gtk.Window) {
_, err := w.Connect("key-press-event", handleKeybinding)
if err != nil {
log.Fatal("failed to connect key-press-event:", err)
}
}
func handleKeybinding(_ *gtk.Window, ev *gdk.Event) bool {
keyEvent := &gdk.EventKey{ev}
switch keyEvent.KeyVal() {
case gdk.KEY_Up, gdk.KEY_Down:
offset := -1
if keyEvent.KeyVal() == gdk.KEY_Down {
offset = 1
}
index := 0
row := listBox.GetSelectedRow()
if row != nil {
index = row.GetIndex()
}
row = listBox.GetRowAtIndex(index + offset)
if row != nil {
listBox.SelectRow(row)
row.GrabFocus()
inputView.GrabFocus()
}
return true
case gdk.KEY_Return:
runInTerminal := keyEvent.State()&uint(gdk.GDK_CONTROL_MASK) != 0
err := listSelect(inputView, runInTerminal)
if err != nil {
log.Fatal(err)
}
return true
case gdk.KEY_Escape:
os.Exit(0)
}
return false
}

View File

@ -72,50 +72,6 @@ func load() {
loaded <- true
}
func setupKeyBindings(w *gtk.Window) {
_, err := w.Connect("key-press-event", handleKeybinding)
if err != nil {
log.Fatal("failed to connect key-press-event:", err)
}
}
func handleKeybinding(_ *gtk.Window, ev *gdk.Event) bool {
keyEvent := &gdk.EventKey{ev}
switch keyEvent.KeyVal() {
case gdk.KEY_Up, gdk.KEY_Down:
offset := -1
if keyEvent.KeyVal() == gdk.KEY_Down {
offset = 1
}
index := 0
row := listBox.GetSelectedRow()
if row != nil {
index = row.GetIndex()
}
row = listBox.GetRowAtIndex(index + offset)
if row != nil {
listBox.SelectRow(row)
row.GrabFocus()
inputView.GrabFocus()
}
return true
case gdk.KEY_Return:
err := listSelect(inputView)
if err != nil {
log.Fatal(err)
}
return true
case gdk.KEY_Escape:
os.Exit(0)
}
return false
}
func main() {
go load()
@ -149,7 +105,7 @@ func main() {
log.Fatal("failed to create application window:", err)
}
<-loaded
setupKeyBindings(w)
go gmenu.HandleInput(func(input string) {
_, err := glib.IdleAdd(updateList, input)
@ -158,14 +114,14 @@ func main() {
}
})
<-loaded
container := newBox(gtk.ORIENTATION_VERTICAL)
initList(container)
w.Add(container)
setupKeyBindings(w)
w.ShowAll()
gtk.Main()