gtkmenu: Run application in terminal on CTRL+Enter
parent
3a492a6414
commit
34cc749965
12
README.md
12
README.md
|
@ -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).
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue