Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bar/bar.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ func NewBar(
return nil, fmt.Errorf("x create: %w", err)
}

// Dont show over full screen apps
win.Stack(xproto.StackModeBelow)

// Make this window close gracefully.
win.WMGracefulClose(func(w *xwindow.Window) {
xevent.Detach(w.X, w.Id)
Expand Down
86 changes: 86 additions & 0 deletions lib/bspwm/bspwm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package bspwm

import (
"bufio"
"os/exec"
"regexp"
)

type Desktop struct {
Num int64 `json:"num"`
Name string `json:"name"`
Visible bool `json:"visible"`
Focused bool `json:"focused"`
Urgent bool `json:"urgent"`
Monitor string `json:"monitor"`
}

//type Monitor struct {
// Desktops []Desktop `json:"desktops"`
//}

type BSPWM struct {
//Monitors []Monitor `json:monitors`
desktops []Desktop
notify func(b BSPWM)
}


var desktops []Desktop

func New(notify func(b BSPWM)) *BSPWM {
b := &BSPWM{
notify: notify,
}

go b.subscribe()
return b
}

func (b *BSPWM) subscribe() {
montiorRegExp := regexp.MustCompile(`(^W|:)[Mm][^L]+`)
displayNameRegExp := regexp.MustCompile(`^(W|:)[Mm][^:]+`)
desktopRegExp := regexp.MustCompile(`[oOuUfF][^:]+`)

cmd := exec.Command("bspc", "subscribe", "report")
stdout, _ := cmd.StdoutPipe()
cmd.Start()

scanner := bufio.NewScanner(stdout)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
var desktops []Desktop
bspcStatus := scanner.Text()
monitors := montiorRegExp.FindAllString(bspcStatus, -1)
for _,monitor := range monitors {

desktopMatches := desktopRegExp.FindAllString(monitor, -1)
displayName := displayNameRegExp.FindString(monitor)[2:]

for _,bwk := range desktopMatches {
name := bwk[1]
status := bwk[0]

desktops = append(desktops, Desktop{
int64(name),
string(name),
true,
status == 'O' || status == 'F',
status == 'O' || status == 'F',
displayName,
})
}
}
b.setDesktops(desktops)
}
cmd.Wait()
}

func (b *BSPWM) setDesktops(dsks []Desktop) {
desktops = dsks
b.notify(*b)
}

func GetDesktops() []Desktop {
return desktops
}
141 changes: 105 additions & 36 deletions ui/module/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,28 @@ package module

import (
"fmt"
"github.com/shimmerglass/bar3x/lib/bspwm"
log "github.com/sirupsen/logrus"
"sort"

"github.com/shimmerglass/bar3x/ui"
"github.com/shimmerglass/bar3x/ui/base"
"github.com/shimmerglass/bar3x/ui/markup"
log "github.com/sirupsen/logrus"
"go.i3wm.org/i3/v4"
)

const WM_I3 = "i3"
const WM_BSPWM = "bspwm"

type workspace struct {
Num int64 `json:"num"`
Name string `json:"name"`
Visible bool `json:"visible"`
Focused bool `json:"focused"`
Urgent bool `json:"urgent"`
Display string `json:"display"`
}

type workspaceIndicator struct {
Root *base.Sizer
Rect *base.Rect
Expand All @@ -24,11 +37,13 @@ type Workspaces struct {

mk *markup.Markup
display string
wm string
maxWidth int
onlyCurrent bool

Row *base.Row
els []*workspaceIndicator
workspaces []workspace
}

func NewWorkspaces(p ui.ParentDrawable, mk *markup.Markup) *Workspaces {
Expand All @@ -48,32 +63,77 @@ func (m *Workspaces) Init() error {
}
m.Root = root
m.display = m.Context().MustString("display")
//m.update()

go func() {
m.update()
er := i3.Subscribe(i3.WorkspaceEventType)
for er.Next() {
m.update()
if m.wm == WM_I3 {
m.i3Update()

er := i3.Subscribe(i3.WorkspaceEventType)
for er.Next() {
m.i3Update()
}
} else if m.wm == WM_BSPWM {
bspwm.New(func (b bspwm.BSPWM){
m.bspwmUpdate()
})
}
}()

return err
}

func (m *Workspaces) update() {
wks, err := i3.GetWorkspaces()
func (m *Workspaces) i3Update() {
i3wks, err := i3.GetWorkspaces()
if err != nil {
log.Errorf("Workspaces: %s", err)
return
}

wks := []workspace{}

for _, i3wk := range i3wks {
wks = append(wks, workspace{
i3wk.Num,
i3wk.Name,
i3wk.Visible,
i3wk.Focused,
i3wk.Urgent,
i3wk.Output,
})
}

m.SetWorkspaces(wks)
}
func (m *Workspaces) bspwmUpdate() {
bdsks := bspwm.GetDesktops()
wks := []workspace{}

for _, bdsk := range bdsks {
wks = append(wks, workspace{
bdsk.Num,
bdsk.Name,
bdsk.Visible,
bdsk.Focused,
bdsk.Urgent,
bdsk.Monitor,
})
}

m.SetWorkspaces(wks)
}

func (m *Workspaces) SetWorkspaces(wks []workspace) {
sort.Slice(wks, func(i, j int) bool {
return wks[i].Num < wks[j].Num
})

m.workspaces = wks
m.update()
}
func (m *Workspaces) update() {
j := 0
for _, wk := range wks {
if wk.Output != m.display {
for _, wk := range m.workspaces {
if wk.Display != m.display {
continue
}
if m.onlyCurrent && !wk.Visible {
Expand All @@ -88,47 +148,49 @@ func (m *Workspaces) update() {

switch {
case !wk.Visible && !wk.Focused:
el.Rect.SetColor(m.Context().MustColor("neutral_color"))
el.Rect.SetColor(m.Context().MustColor("bg_color"))
el.Text.SetColor(m.Context().MustColor("neutral_light_color"))
el.Indicator.SetColor(m.Context().MustColor("neutral_color"))
case wk.Visible && !wk.Focused:
el.Rect.SetColor(m.Context().MustColor("neutral_color"))
el.Rect.SetColor(m.Context().MustColor("bg_color"))
el.Text.SetColor(m.Context().MustColor("text_color"))
el.Indicator.SetColor(m.Context().MustColor("neutral_light_color"))
case wk.Visible && wk.Focused:
el.Rect.SetColor(m.Context().MustColor("neutral_color"))
el.Rect.SetColor(m.Context().MustColor("bg_color"))
el.Text.SetColor(m.Context().MustColor("text_color"))
el.Indicator.SetColor(m.Context().MustColor("accent_color"))
}

el.Text.SetText(wk.Name)
el.Root.SetVisible(true)

func(wk i3.Workspace) {
el.Root.SetOnLeftClick(func(ui.Event) bool {
i3.RunCommand(fmt.Sprintf("workspace %s", wk.Name))
return false
})

el.Root.SetOnPointerEnter(func(ui.Event) bool {
el.Indicator.SetColor(m.Context().MustColor("accent_color"))
el.Indicator.Notify()
return true
})
if m.wm == WM_I3 {
func(wk workspace) {
el.Root.SetOnLeftClick(func(ui.Event) bool {
i3.RunCommand(fmt.Sprintf("workspace %s", wk.Name))
return false
})

el.Root.SetOnPointerLeave(func(ui.Event) bool {
switch {
case wk.Focused:
el.Root.SetOnPointerEnter(func(ui.Event) bool {
el.Indicator.SetColor(m.Context().MustColor("accent_color"))
case wk.Visible:
el.Indicator.SetColor(m.Context().MustColor("neutral_light_color"))
default:
el.Indicator.SetColor(m.Context().MustColor("neutral_color"))
}
el.Indicator.Notify()
return true
})
}(wk)
el.Indicator.Notify()
return true
})

el.Root.SetOnPointerLeave(func(ui.Event) bool {
switch {
case wk.Focused:
el.Indicator.SetColor(m.Context().MustColor("accent_color"))
case wk.Visible:
el.Indicator.SetColor(m.Context().MustColor("neutral_light_color"))
default:
el.Indicator.SetColor(m.Context().MustColor("neutral_color"))
}
el.Indicator.Notify()
return true
})
}(wk)
}

j++
}
Expand Down Expand Up @@ -182,6 +244,13 @@ func (m *Workspaces) SetMaxWidth(v int) {
m.maxWidth = v
}

func (m *Workspaces) WM() string {
return m.wm
}
func (m *Workspaces) SetWM(v string) {
m.wm = v
}

func (m *Workspaces) OnlyCurrent() bool {
return m.onlyCurrent
}
Expand Down