diff --git a/client.go b/client.go index ec47145..7f28419 100644 --- a/client.go +++ b/client.go @@ -22,6 +22,17 @@ type client struct { type Client interface { GetTree(context.Context) (*Node, error) RunCommand(context.Context, string) ([]RunCommandReply, error) + GetWorkspaces(context.Context) ([]Workspace, error) + GetMarks(context.Context) ([]string, error) + GetOutputs(context.Context) ([]Output, error) + GetBarIDs(context.Context) ([]BarID, error) + GetBarConfig(context.Context, BarID) (*BarConfig, error) + GetVersion(context.Context) (*Version, error) + GetBindingModes(context.Context) ([]string, error) + GetConfig(context.Context) (*Config, error) + SendTick(context.Context, string) (*TickReply, error) + GetInputs(context.Context) ([]Input, error) + GetSeats(context.Context) ([]Seat, error) Close() error } @@ -140,3 +151,113 @@ func (c *client) RunCommand(ctx context.Context, command string) ([]RunCommandRe return replies, err } + +func (c *client) GetWorkspaces(ctx context.Context) ([]Workspace, error) { + msg, err := c.roundTrip(ctx, messageTypeGetWorkspaces, nil) + if err != nil { + return nil, err + } + + var ret []Workspace + return ret, msg.Decode(&ret) +} + +func (c *client) GetOutputs(ctx context.Context) ([]Output, error) { + msg, err := c.roundTrip(ctx, messageTypeGetOutputs, nil) + if err != nil { + return nil, err + } + + var ret []Output + return ret, msg.Decode(&ret) +} + +func (c *client) GetMarks(ctx context.Context) ([]string, error) { + msg, err := c.roundTrip(ctx, messageTypeGetMarks, nil) + if err != nil { + return nil, err + } + + var ret []string + return ret, msg.Decode(&ret) +} + +func (c *client) GetBarIDs(ctx context.Context) ([]BarID, error) { + msg, err := c.roundTrip(ctx, messageTypeGetBarConfig, nil) + if err != nil { + return nil, err + } + + var ret []BarID + return ret, msg.Decode(&ret) +} + +func (c *client) GetBarConfig(ctx context.Context, id BarID) (*BarConfig, error) { + msg, err := c.roundTrip(ctx, messageTypeGetBarConfig, []byte(id)) + if err != nil { + return nil, err + } + + var ret BarConfig + return &ret, msg.Decode(&ret) +} + +func (c *client) GetVersion(ctx context.Context) (*Version, error) { + msg, err := c.roundTrip(ctx, messageTypeGetVersion, nil) + if err != nil { + return nil, err + } + + var ret Version + return &ret, msg.Decode(&ret) +} + +func (c *client) GetBindingModes(ctx context.Context) ([]string, error) { + msg, err := c.roundTrip(ctx, messageTypeGetBindingModes, nil) + if err != nil { + return nil, err + } + + var ret []string + return ret, msg.Decode(&ret) +} + +func (c *client) GetConfig(ctx context.Context) (*Config, error) { + msg, err := c.roundTrip(ctx, messageTypeGetConfig, nil) + if err != nil { + return nil, err + } + + var ret Config + return &ret, msg.Decode(&ret) +} + +func (c *client) SendTick(ctx context.Context, payload string) (*TickReply, error) { + msg, err := c.roundTrip(ctx, messageTypeSendTick, []byte(payload)) + if err != nil { + return nil, err + } + + var ret TickReply + return &ret, msg.Decode(&ret) +} + +func (c *client) GetInputs(ctx context.Context) ([]Input, error) { + msg, err := c.roundTrip(ctx, messageTypeGetInputs, nil) + if err != nil { + return nil, err + } + + var ret []Input + return ret, msg.Decode(&ret) +} + +func (c *client) GetSeats(ctx context.Context) ([]Seat, error) { + msg, err := c.roundTrip(ctx, messageTypeGetSeats, nil) + if err != nil { + return nil, err + } + + var ret []Seat + return ret, msg.Decode(&ret) +} diff --git a/cmd/sway-focused/main.go b/cmd/sway-focused/main.go new file mode 100644 index 0000000..c7bc9ca --- /dev/null +++ b/cmd/sway-focused/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "syscall" + + sway "github.com/joshuarubin/go-sway" + "github.com/joshuarubin/lifecycle" +) + +func main() { + if err := run(); err != nil && !isSignal(err) { + fmt.Fprintf(os.Stderr, "%+v\n", err) + os.Exit(1) + } +} + +func isSignal(err error, sigs ...os.Signal) bool { + serr, ok := err.(lifecycle.ErrSignal) + if !ok { + return false + } + switch serr.Signal { + case syscall.SIGINT, syscall.SIGTERM: + return true + } + return false +} + +func run() error { + ctx := lifecycle.New(context.Background()) + + client, err := sway.New(ctx) + if err != nil { + return err + } + defer client.Close() + + fh := focusHandler(client) + + n, err := client.GetTree(ctx) + if err != nil { + return err + } + + fh(ctx, n.FocusedNode()) + + h := sway.EventHandler{ + Window: func(ctx context.Context, e sway.WindowEvent) { + if e.Change != "focus" { + return + } + fh(ctx, e.Container.FocusedNode()) + }, + } + + lifecycle.GoErr(ctx, func() error { + return sway.Subscribe(ctx, h, sway.EventTypeWindow) + }) + + return lifecycle.Wait(ctx) +} + +func focusHandler(client sway.Client) func(context.Context, *sway.Node) { + return func(ctx context.Context, node *sway.Node) { + if node == nil { + return + } + + opt := "none" + if node.AppID == nil || *node.AppID != "kitty" { + opt = "altwin:ctrl_win" + } + + if _, err := client.RunCommand(ctx, `input '*' xkb_options `+opt); err != nil { + log.Println(err) + } + } +} diff --git a/go.mod b/go.mod index 1af4ebf..de8960f 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/joshuarubin/go-sway go 1.12 require ( + github.com/joshuarubin/lifecycle v0.0.3 github.com/stretchr/testify v1.3.0 // indirect go.uber.org/atomic v1.3.2 // indirect go.uber.org/multierr v1.1.0 diff --git a/go.sum b/go.sum index a4925fd..1d1d19e 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/joshuarubin/lifecycle v0.0.3 h1:CpBhY0kS+tln6u7/p3I84cu8sDzluVIF/lCO9BpodjQ= +github.com/joshuarubin/lifecycle v0.0.3/go.mod h1:uOdzFKF/2+tKiVSF2lLCuI1dQZo35yXr93rPOd7Hsio= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -9,3 +11,5 @@ go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/internal.go b/internal.go index 27edf52..4c8ba1a 100644 --- a/internal.go +++ b/internal.go @@ -36,18 +36,19 @@ const ( messageTypeGetBindingModes messageTypeGetConfig messageTypeSendTick - messageTypeSync + messageTypeGetInputs = 100 + messageTypeGetSeats = 101 ) const ( - eventReplyTypeWorkspace messageType = 0x80000000 - eventReplyTypeMode messageType = 0x80000002 - eventReplyTypeWindow messageType = 0x80000003 - eventReplyTypeBarConfigUpdate messageType = 0x80000004 - eventReplyTypeBinding messageType = 0x80000005 - eventReplyTypeShutdown messageType = 0x80000006 - eventReplyTypeTick messageType = 0x80000007 - eventReplyTypeBarStatusUpdate messageType = 0x80000014 + eventTypeWorkspace messageType = 0x80000000 + eventTypeMode messageType = 0x80000002 + eventTypeWindow messageType = 0x80000003 + eventTypeBarConfigUpdate messageType = 0x80000004 + eventTypeBinding messageType = 0x80000005 + eventTypeShutdown messageType = 0x80000006 + eventTypeTick messageType = 0x80000007 + eventTypeBarStatusUpdate messageType = 0x80000014 ) var magic = [6]byte{'i', '3', '-', 'i', 'p', 'c'} diff --git a/socket_test.go b/socket_test.go index 068a77e..bb88e92 100644 --- a/socket_test.go +++ b/socket_test.go @@ -2,6 +2,8 @@ package sway_test import ( "context" + "encoding/json" + "fmt" "log" "testing" "time" @@ -9,8 +11,13 @@ import ( sway "github.com/joshuarubin/go-sway" ) +func printJSON(v interface{}) { + out, _ := json.MarshalIndent(v, "", " ") + fmt.Println(string(out)) +} + func TestSocket(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() client, err := sway.New(ctx) @@ -24,13 +31,90 @@ func TestSocket(t *testing.T) { t.Fatal(err) } - fh := focusHandler(client) + workspaces, err := client.GetWorkspaces(ctx) + if err != nil { + t.Fatal(err) + } + printJSON(workspaces) + + outputs, err := client.GetOutputs(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(outputs) + + marks, err := client.GetMarks(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(marks) + + barIDs, err := client.GetBarIDs(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(barIDs) + + for _, id := range barIDs { + config, err := client.GetBarConfig(ctx, id) + if err != nil { + t.Fatal(err) + } + printJSON(config) + } + + version, err := client.GetVersion(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(*version) + + bindingModes, err := client.GetBindingModes(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(bindingModes) + + config, err := client.GetConfig(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(config) + + tick, err := client.SendTick(ctx, "foo") + if err != nil { + t.Fatal(err) + } + + printJSON(tick) + + inputs, err := client.GetInputs(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(inputs) + + seats, err := client.GetSeats(ctx) + if err != nil { + t.Fatal(err) + } + + printJSON(seats) + + fh := focusHandler(client) fh(ctx, n.FocusedNode()) h := sway.EventHandler{ Window: func(ctx context.Context, e sway.WindowEvent) { - if e.Change != sway.WindowChangeFocus { + if e.Change != "focus" { return } fh(ctx, e.Container.FocusedNode()) diff --git a/subscribe.go b/subscribe.go index 292db84..a533a65 100644 --- a/subscribe.go +++ b/subscribe.go @@ -18,9 +18,14 @@ const ( ) type EventHandler struct { - Workspace func(context.Context, WorkspaceEvent) - Window func(context.Context, WindowEvent) - Shutdown func(context.Context, ShutdownEvent) + Workspace func(context.Context, WorkspaceEvent) + Mode func(context.Context, ModeEvent) + Window func(context.Context, WindowEvent) + BarConfigUpdate func(context.Context, BarConfigUpdateEvent) + Binding func(context.Context, BindingEvent) + Shutdown func(context.Context, ShutdownEvent) + Tick func(context.Context, TickEvent) + BarStatusUpdate func(context.Context, BarStatusUpdateEvent) } func Subscribe(ctx context.Context, handler EventHandler, events ...EventType) error { @@ -48,43 +53,77 @@ func Subscribe(ctx context.Context, handler EventHandler, events ...EventType) e func (h EventHandler) process(ctx context.Context, reply *message) { switch reply.Type { - case eventReplyTypeWorkspace: + case eventTypeWorkspace: if h.Workspace == nil { return } var e WorkspaceEvent - if err := reply.Decode(&e); err != nil { + if err := reply.Decode(&e); err == nil { + h.Workspace(ctx, e) + } + case eventTypeMode: + if h.Mode == nil { return } - h.Workspace(ctx, e) - case eventReplyTypeMode: - case eventReplyTypeWindow: + var e ModeEvent + if err := reply.Decode(&e); err == nil { + h.Mode(ctx, e) + } + case eventTypeWindow: if h.Window == nil { return } var e WindowEvent - if err := reply.Decode(&e); err != nil { + if err := reply.Decode(&e); err == nil { + h.Window(ctx, e) + } + case eventTypeBarConfigUpdate: + if h.BarConfigUpdate == nil { return } - h.Window(ctx, e) - case eventReplyTypeBarConfigUpdate: - case eventReplyTypeBinding: - case eventReplyTypeShutdown: + var e BarConfigUpdateEvent + if err := reply.Decode(&e); err == nil { + h.BarConfigUpdate(ctx, e) + } + case eventTypeBinding: + if h.Binding == nil { + return + } + + var e BindingEvent + if err := reply.Decode(&e); err == nil { + h.Binding(ctx, e) + } + case eventTypeShutdown: if h.Shutdown == nil { return } var e ShutdownEvent - if err := reply.Decode(&e); err != nil { + if err := reply.Decode(&e); err == nil { + h.Shutdown(ctx, e) + } + case eventTypeTick: + if h.Tick == nil { return } - h.Shutdown(ctx, e) - case eventReplyTypeTick: - case eventReplyTypeBarStatusUpdate: + var e TickEvent + if err := reply.Decode(&e); err == nil { + h.Tick(ctx, e) + } + case eventTypeBarStatusUpdate: + if h.BarStatusUpdate == nil { + return + } + + var e BarStatusUpdateEvent + if err := reply.Decode(&e); err == nil { + h.BarStatusUpdate(ctx, e) + } } } diff --git a/types.go b/types.go index 59b97bf..b39c3e9 100644 --- a/types.go +++ b/types.go @@ -1,73 +1,44 @@ package sway -type NodeID int64 - -type NodeType string - -const ( - NodeTypeRoot NodeType = "root" - NodeTypeOutput NodeType = "output" - NodeTypeCon NodeType = "con" - NodeTypeFloatingCon NodeType = "floating_con" - NodeTypeWorkspace NodeType = "workspace" -) - -type BorderStyle string - -const ( - BorderStyleNormal BorderStyle = "normal" - BorderStyleNone BorderStyle = "none" - BorderStylePixel BorderStyle = "pixel" - BorderStyleCSD BorderStyle = "csd" -) - -type Layout string - -const ( - LayoutSplitH Layout = "splith" - LayoutSplitV Layout = "splitv" - LayoutStacked Layout = "stacked" - LayoutTabbed Layout = "tabbed" - LayoutOutput Layout = "output" -) +import "encoding/json" type Rect struct { - X int64 `json:"x"` - Y int64 `json:"y"` - Width int64 `json:"width"` - Height int64 `json:"height"` + X int64 `json:"x,omitempty"` + Y int64 `json:"y,omitempty"` + Width int64 `json:"width,omitempty"` + Height int64 `json:"height,omitempty"` } type WindowProperties struct { - Title string `json:"title"` - Instance string `json:"instance"` - Class string `json:"class"` - Role string `json:"window_role"` - TransientFor NodeID `json:"transient_for"` + Title string `json:"title,omitempty"` + Instance string `json:"instance,omitempty"` + Class string `json:"class,omitempty"` + Role string `json:"window_role,omitempty"` + TransientFor int64 `json:"transient_for,omitempty"` } type Node struct { - ID NodeID `json:"id"` - Name string `json:"name"` - Type NodeType `json:"type"` - Border BorderStyle `json:"border"` - CurrentBorderWidth int64 `json:"current_border_width"` - Layout Layout `json:"layout"` - Percent *float64 `json:"percent"` - Rect Rect `json:"rect"` - WindowRect Rect `json:"window_rect"` - DecoRect Rect `json:"deco_rect"` - Geometry Rect `json:"geometry"` - Urgent *bool `json:"urgent"` - Focused bool `json:"focused"` - Focus []NodeID `json:"focus"` - Nodes []*Node `json:"nodes"` - FloatingNodes []*Node `json:"floating_nodes"` - Representation *string `json:"representation"` - AppID *string `json:"app_id"` - PID *uint32 `json:"pid"` - Window *int64 `json:"window"` - WindowProperties *WindowProperties `json:"window_properties"` + ID int64 `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Border string `json:"border,omitempty"` + CurrentBorderWidth int64 `json:"current_border_width,omitempty"` + Layout string `json:"layout,omitempty"` + Percent *float64 `json:"percent,omitempty"` + Rect Rect `json:"rect,omitempty"` + WindowRect Rect `json:"window_rect,omitempty"` + DecoRect Rect `json:"deco_rect,omitempty"` + Geometry Rect `json:"geometry,omitempty"` + Urgent *bool `json:"urgent,omitempty"` + Focused bool `json:"focused,omitempty"` + Focus []int64 `json:"focus,omitempty"` + Nodes []*Node `json:"nodes,omitempty"` + FloatingNodes []*Node `json:"floating_nodes,omitempty"` + Representation *string `json:"representation,omitempty"` + AppID *string `json:"app_id,omitempty"` + PID *uint32 `json:"pid,omitempty"` + Window *int64 `json:"window,omitempty"` + WindowProperties *WindowProperties `json:"window_properties,omitempty"` } func (n *Node) FocusedNode() *Node { @@ -92,52 +63,194 @@ func (n *Node) FocusedNode() *Node { type Event interface{} -type WorkspaceChange string - -const ( - WorkspaceChangeInit WorkspaceChange = "init" - WorkspaceChangeEmpty WorkspaceChange = "empty" - WorkspaceChangeFocus WorkspaceChange = "focus" - WorkspaceChangeMove WorkspaceChange = "move" - WorkspaceChangeRename WorkspaceChange = "rename" - WorkspaceChangeUrgent WorkspaceChange = "urgent" - WorkspaceChangeReload WorkspaceChange = "reload" -) - type WorkspaceEvent struct { - Change WorkspaceChange `json:"change"` - Current *Node `json:"current"` - Old *Node `json:"old"` + Change string `json:"change,omitempty"` + Current *Node `json:"current,omitempty"` + Old *Node `json:"old,omitempty"` } -type WindowChange string - -const ( - WindowChangeNew WindowChange = "new" - WindowChangeClose WindowChange = "close" - WindowChangeFocus WindowChange = "focus" - WindowChangeTitle WindowChange = "title" - WindowChangeFullscreenMode WindowChange = "fullscreen_mode" - WindowChangeMove WindowChange = "move" - WindowChangeFloating WindowChange = "floating" - WindowChangeUrgent WindowChange = "urgent" - WindowChangeMark WindowChange = "mark" -) - type WindowEvent struct { - Change WindowChange `json:"change"` - Container Node `json:"container"` + Change string `json:"change,omitempty"` + Container Node `json:"container,omitempty"` } -type ShutdownChange string - -const ShutdownChangeExit ShutdownChange = "exit" - type ShutdownEvent struct { - Change ShutdownChange `json:"change"` + Change string `json:"change,omitempty"` } type RunCommandReply struct { - Success bool `json:"success"` - Error string `json:"error"` + Success bool `json:"success,omitempty"` + Error string `json:"error,omitempty"` +} + +type Workspace struct { + Num int64 `json:"num,omitempty"` + Name string `json:"name,omitempty"` + Visible bool `json:"visible,omitempty"` + Focused bool `json:"focused,omitempty"` + Urgent bool `json:"urgent,omitempty"` + Rect Rect `json:"rect,omitempty"` + Output string `json:"output,omitempty"` +} + +type Refresh float64 + +func (r *Refresh) UnmarshalJSON(raw []byte) error { + var n int64 + if err := json.Unmarshal(raw, &n); err != nil { + return err + } + *r = Refresh(float64(n) / 1000) + return nil +} + +type OutputMode struct { + Width int64 `json:"width,omitempty"` + Height int64 `json:"height,omitempty"` + Refresh Refresh `json:"refresh,omitempty"` +} + +type Output struct { + Name string `json:"name,omitempty"` + Make string `json:"make,omitempty"` + Model string `json:"model,omitempty"` + Serial string `json:"serial,omitempty"` + Active bool `json:"active,omitempty"` + Primary bool `json:"primary,omitempty"` + Scale float64 `json:"scale,omitempty"` + Transform string `json:"transform,omitempty"` + CurrentWorkspace string `json:"current_workspace,omitempty"` + Modes []OutputMode `json:"modes,omitempty"` + CurrentMode OutputMode `json:"current_mode,omitempty"` + Rect Rect `json:"rect,omitempty"` +} + +type BarConfigGaps struct { + Top int64 `json:"top,omitempty"` + Right int64 `json:"right,omitempty"` + Bottom int64 `json:"bottom,omitempty"` + Left int64 `json:"left,omitempty"` +} + +type BarConfigColors struct { + Background string `json:"background,omitempty"` + Statusline string `json:"statusline,omitempty"` + Separator string `json:"separator,omitempty"` + FocusedBackground string `json:"focused_background,omitempty"` + FocusedStatusline string `json:"focused_statusline,omitempty"` + FocusedSeparator string `json:"focused_separator,omitempty"` + FocusedWorkspaceText string `json:"focused_workspace_text,omitempty"` + FocusedWorkspaceBG string `json:"focused_workspace_bg,omitempty"` + FocusedWorkspaceBorder string `json:"focused_workspace_border,omitempty"` + ActiveWorkspaceText string `json:"active_workspace_text,omitempty"` + ActiveWorkspaceBG string `json:"active_workspace_bg,omitempty"` + ActiveWorkspaceBorder string `json:"active_workspace_border,omitempty"` + InactiveWorkspaceText string `json:"inactive_workspace_text,omitempty"` + InactiveWorkspaceBG string `json:"inactive_workspace_bg,omitempty"` + InactiveWorkspaceBorder string `json:"inactive_workspace_border,omitempty"` + UrgentWorkspaceText string `json:"urgent_workspace_text,omitempty"` + UrgentWorkspaceBG string `json:"urgent_workspace_bg,omitempty"` + UrgentWorkspaceBorder string `json:"urgent_workspace_border,omitempty"` + BindingModeText string `json:"binding_mode_text,omitempty"` + BindingModeBG string `json:"binding_mode_bg,omitempty"` + BindingModeBorder string `json:"binding_mode_border,omitempty"` +} + +type BarID string + +type BarConfigUpdateEvent = BarConfig + +type BarConfig struct { + ID BarID `json:"id,omitempty"` + Mode string `json:"mode,omitempty"` + Position string `json:"position,omitempty"` + StatusCommand string `json:"status_command,omitempty"` + Font string `json:"font,omitempty"` + WorkspaceButtons bool `json:"workspace_buttons,omitempty"` + BindingModeIndicator bool `json:"binding_mode_indicator,omitempty"` + Verbose bool `json:"verbose,omitempty"` + Colors BarConfigColors `json:"colors,omitempty"` + Gaps BarConfigGaps `json:"gaps,omitempty"` + BarHeight int64 `json:"bar_height,omitempty"` + StatusPadding int64 `json:"status_padding,omitempty"` + StatusEdgePadding int64 `json:"status_edge_padding,omitempty"` +} + +type Version struct { + Major int64 `json:"major,omitempty"` + Minor int64 `json:"minor,omitempty"` + Patch int64 `json:"patch,omitempty"` + HumanReadable string `json:"human_readable,omitempty"` + LoadedConfigFileName string `json:"loaded_config_file_name,omitempty"` +} + +type Config struct { + Config string `json:"config,omitempty"` +} + +type TickReply struct { + Success bool `json:"success,omitempty"` +} + +type LibInput struct { + SendEvents string `json:"send_events,omitempty"` + Tap string `json:"tap,omitempty"` + TapButtonMap string `json:"tap_button_map,omitempty"` + TapDrag string `json:"tap_drag,omitempty"` + TapDragLock string `json:"tap_drag_lock,omitempty"` + AccelSpeed float64 `json:"accel_speed,omitempty"` + AccelProfile string `json:"accel_profile,omitempty"` + NaturalScroll string `json:"natural_scroll,omitempty"` + LeftHanded string `json:"left_handed,omitempty"` + ClickMethod string `json:"click_method,omitempty"` + MiddleEmulation string `json:"middle_emulation,omitempty"` + ScrollMethod string `json:"scroll_method,omitempty"` + ScrollButton int64 `json:"scroll_button,omitempty"` + DWT string `json:"dwt,omitempty"` +} + +type Input struct { + Identifier string `json:"identifier,omitempty"` + Name string `json:"name,omitempty"` + Vendor int64 `json:"vendor,omitempty"` + Product int64 `json:"product,omitempty"` + Type string `json:"type,omitempty"` + XKBActiveLayoutName *string `json:"xkb_active_layout_name,omitempty"` + LibInput *LibInput `json:"libinput,omitempty"` +} + +type Seat struct { + Name string `json:"name,omitempty"` + Capabilities int64 `json:"capabilities,omitempty"` + Focus int64 `json:"focus,omitempty"` + Devices []Input `json:"devices,omitempty"` +} + +type ModeEvent struct { + Change string `json:"change,omitempty"` + PangoMarkup bool `json:"pango_markup,omitempty"` +} + +type Binding struct { + Change string `json:"change,omitempty"` + Command string `json:"command,omitempty"` + EventStateMask []string `json:"event_state_mask,omitempty"` + InputCode int64 `json:"input_code,omitempty"` + Symbol *string `json:"symbol,omitempty"` + InputType string `json:"input_type,omitempty"` +} + +type BindingEvent struct { + Change string `json:"change,omitempty"` + Binding Binding `json:"binding,omitempty"` +} + +type TickEvent struct { + First bool `json:"first,omitempty"` + Payload string `json:"payload,omitempty"` +} + +type BarStatusUpdateEvent struct { + ID string `json:"id,omitempty"` + VisibleByModifier bool `json:"visible_by_modifier,omitempty"` }