[yambar] Add custom sway module
Script module for sway that handles multi-monitor setups a little bit better, and that shows current mode.
This commit is contained in:
parent
1cd1dfe2e0
commit
1914e3f0db
2 changed files with 226 additions and 20 deletions
|
@ -75,27 +75,122 @@ bar:
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
left:
|
left:
|
||||||
- i3:
|
#- i3:
|
||||||
sort: ascending
|
#sort: ascending
|
||||||
|
#content:
|
||||||
|
#"":
|
||||||
|
#map:
|
||||||
|
#default: {string: {text: "{name}", foreground: *col_fg_alt, margin: 7}}
|
||||||
|
#conditions:
|
||||||
|
#state == focused: {string: {text: "{name}", margin: 7}}
|
||||||
|
|
||||||
|
- script:
|
||||||
|
path: /home/midgard/.config/yambar/sway.py
|
||||||
|
anchors:
|
||||||
|
monitor_sep: &monitor_sep {string: {text: "|"}}
|
||||||
|
ws_common: &ws_common {left-margin: 7, right-margin: 7}
|
||||||
|
ws_default: &ws_default {foreground: *col_fg_alt, <<: *ws_common}
|
||||||
|
ws_focused: &ws_focused {foreground: *col_fg, <<: *ws_common}
|
||||||
|
ws_visible: &ws_visible {foreground: *col_visible_ws, <<: *ws_common}
|
||||||
content:
|
content:
|
||||||
"":
|
- list:
|
||||||
map:
|
spacing: 0
|
||||||
tag: state
|
items:
|
||||||
default: {string: {text: "{name}", foreground: *col_fg_alt, margin: 7}}
|
- map:
|
||||||
values:
|
default: {string: {text: "{ws0}", <<: *ws_default}}
|
||||||
"focused": {string: {text: "{name}", margin: 7}}
|
conditions:
|
||||||
#current:
|
ws0_state == unused: {empty: {}}
|
||||||
#list:
|
ws0_state == focused: {string: {text: "{ws0}", <<: *ws_focused}}
|
||||||
#left-margin: 25
|
ws0_state == visible: {string: {text: "{ws0}", <<: *ws_visible}}
|
||||||
#spacing: 0
|
- map: {default: {empty: {}}, conditions: {ws1_new_monitor: *monitor_sep}}
|
||||||
#items:
|
- map:
|
||||||
#- { string: {text: "{application}", foreground: *col_fg_alt}}
|
default: {string: {text: "{ws1}", <<: *ws_default}}
|
||||||
#- map:
|
conditions:
|
||||||
#tag: application
|
ws1_state == unused: {empty: {}}
|
||||||
#default: { string: {text: ": ", foreground: *col_fg_alt}}
|
ws1_state == focused: {string: {text: "{ws1}", <<: *ws_focused}}
|
||||||
#values:
|
ws1_state == visible: {string: {text: "{ws1}", <<: *ws_visible}}
|
||||||
#"": {empty: {}}
|
- map: {default: {empty: {}}, conditions: {ws2_new_monitor: *monitor_sep}}
|
||||||
#- { string: {text: "{title}", foreground: *col_fg_alt}}
|
- map:
|
||||||
|
default: {string: {text: "{ws2}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws2_state == unused: {empty: {}}
|
||||||
|
ws2_state == focused: {string: {text: "{ws2}", <<: *ws_focused}}
|
||||||
|
ws2_state == visible: {string: {text: "{ws2}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws3_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws3}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws3_state == unused: {empty: {}}
|
||||||
|
ws3_state == focused: {string: {text: "{ws3}", <<: *ws_focused}}
|
||||||
|
ws3_state == visible: {string: {text: "{ws3}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws4_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws4}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws4_state == unused: {empty: {}}
|
||||||
|
ws4_state == focused: {string: {text: "{ws4}", <<: *ws_focused}}
|
||||||
|
ws4_state == visible: {string: {text: "{ws4}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws5_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws5}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws5_state == unused: {empty: {}}
|
||||||
|
ws5_state == focused: {string: {text: "{ws5}", <<: *ws_focused}}
|
||||||
|
ws5_state == visible: {string: {text: "{ws5}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws6_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws6}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws6_state == unused: {empty: {}}
|
||||||
|
ws6_state == focused: {string: {text: "{ws6}", <<: *ws_focused}}
|
||||||
|
ws6_state == visible: {string: {text: "{ws6}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws7_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws7}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws7_state == unused: {empty: {}}
|
||||||
|
ws7_state == focused: {string: {text: "{ws7}", <<: *ws_focused}}
|
||||||
|
ws7_state == visible: {string: {text: "{ws7}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws8_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws8}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws8_state == unused: {empty: {}}
|
||||||
|
ws8_state == focused: {string: {text: "{ws8}", <<: *ws_focused}}
|
||||||
|
ws8_state == visible: {string: {text: "{ws8}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws9_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws9}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws9_state == unused: {empty: {}}
|
||||||
|
ws9_state == focused: {string: {text: "{ws9}", <<: *ws_focused}}
|
||||||
|
ws9_state == visible: {string: {text: "{ws9}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws10_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws10}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws10_state == unused: {empty: {}}
|
||||||
|
ws10_state == focused: {string: {text: "{ws10}", <<: *ws_focused}}
|
||||||
|
ws10_state == visible: {string: {text: "{ws10}", <<: *ws_visible}}
|
||||||
|
- map: {default: {empty: {}}, conditions: {ws11_new_monitor: *monitor_sep}}
|
||||||
|
- map:
|
||||||
|
default: {string: {text: "{ws11}", <<: *ws_default}}
|
||||||
|
conditions:
|
||||||
|
ws11_state == unused: {empty: {}}
|
||||||
|
ws11_state == focused: {string: {text: "{ws11}", <<: *ws_focused}}
|
||||||
|
ws11_state == visible: {string: {text: "{ws11}", <<: *ws_visible}}
|
||||||
|
- map:
|
||||||
|
default:
|
||||||
|
- {empty: {left-margin: 5}}
|
||||||
|
- string:
|
||||||
|
text: "{mode}"
|
||||||
|
left-margin: 5
|
||||||
|
right-margin: 5
|
||||||
|
deco:
|
||||||
|
background:
|
||||||
|
color: 9c5842d8
|
||||||
|
conditions:
|
||||||
|
mode == default: {empty: {}}
|
||||||
|
|
||||||
- mem:
|
- mem:
|
||||||
interval: 1500
|
interval: 1500
|
||||||
|
|
111
yambar/sway.py
Executable file
111
yambar/sway.py
Executable file
|
@ -0,0 +1,111 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import json
|
||||||
|
import traceback
|
||||||
|
from time import sleep
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
MSGTYPE_GET_WORKSPACES = 1
|
||||||
|
MSGTYPE_SUBSCRIBE = 2
|
||||||
|
MSGTYPE_GET_BINDING_STATE = 12
|
||||||
|
MSGTYPE_EVENT_WORKSPACE = 0x80000000
|
||||||
|
MSGTYPE_EVENT_MODE = 0x80000002
|
||||||
|
|
||||||
|
magic = b"i3-ipc"
|
||||||
|
msg_header = struct.Struct("II")
|
||||||
|
|
||||||
|
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
s.connect(os.getenvb(b"SWAYSOCK"))
|
||||||
|
|
||||||
|
def recv():
|
||||||
|
reply_magic = s.recv(6)
|
||||||
|
assert reply_magic == magic
|
||||||
|
reply_header = s.recv(msg_header.size)
|
||||||
|
reply_length, reply_type = msg_header.unpack(reply_header)
|
||||||
|
reply_payload = s.recv(reply_length)
|
||||||
|
return reply_type, reply_payload
|
||||||
|
|
||||||
|
def msg(msg_type: int, payload: bytes):
|
||||||
|
global s
|
||||||
|
message = (
|
||||||
|
magic +
|
||||||
|
msg_header.pack(len(payload), msg_type) +
|
||||||
|
payload
|
||||||
|
)
|
||||||
|
n_sent_bytes = s.send(message)
|
||||||
|
assert n_sent_bytes == len(message)
|
||||||
|
|
||||||
|
def subscribe(types: List[str]):
|
||||||
|
msg(MSGTYPE_SUBSCRIBE, json.dumps(types).encode("utf-8"))
|
||||||
|
reply = recv()
|
||||||
|
success = json.loads(reply[1])["success"]
|
||||||
|
if not success:
|
||||||
|
raise Exception("Could not subscribe")
|
||||||
|
|
||||||
|
|
||||||
|
def format_workspaces(workspaces):
|
||||||
|
result = []
|
||||||
|
last_output = None
|
||||||
|
for i, ws in enumerate(sorted(workspaces, key=lambda x: (x["output"], x["num"], x["name"]))):
|
||||||
|
name = ws["name"]
|
||||||
|
|
||||||
|
new_monitor = last_output is not None and last_output != ws["output"]
|
||||||
|
last_output = ws["output"]
|
||||||
|
|
||||||
|
state = (
|
||||||
|
"focused" if ws["focused"] else
|
||||||
|
"visible" if ws["visible"] else
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
result.append(f"ws{i}|string|{ws['name']}")
|
||||||
|
result.append(f"ws{i}_state|string|{state}")
|
||||||
|
result.append(f"ws{i}_new_monitor|bool|{'true' if new_monitor else 'false'}")
|
||||||
|
|
||||||
|
while i <= 11:
|
||||||
|
result.append(f"ws{i}|string|")
|
||||||
|
result.append(f"ws{i}_state|string|unused")
|
||||||
|
result.append(f"ws{i}_new_monitor|bool|false")
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return "\n".join(result)
|
||||||
|
|
||||||
|
|
||||||
|
msg(MSGTYPE_GET_BINDING_STATE, b'')
|
||||||
|
state_mode = json.loads(recv()[1])["name"]
|
||||||
|
msg(MSGTYPE_GET_WORKSPACES, b'')
|
||||||
|
state_workspaces = json.loads(recv()[1])
|
||||||
|
|
||||||
|
|
||||||
|
def print_state():
|
||||||
|
global state_workspaces
|
||||||
|
global state_mode
|
||||||
|
print(f"""{format_workspaces(state_workspaces)}
|
||||||
|
mode|string|{state_mode}
|
||||||
|
""", flush=True)
|
||||||
|
sleep(0.01)
|
||||||
|
|
||||||
|
print_state()
|
||||||
|
|
||||||
|
subscribe(["workspace", "mode"])
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
item_type, item = recv()
|
||||||
|
|
||||||
|
if item_type == MSGTYPE_GET_WORKSPACES:
|
||||||
|
state_workspaces = json.loads(item)
|
||||||
|
print_state()
|
||||||
|
elif item_type == MSGTYPE_EVENT_WORKSPACE:
|
||||||
|
msg(MSGTYPE_GET_WORKSPACES, b'')
|
||||||
|
elif item_type == MSGTYPE_EVENT_MODE:
|
||||||
|
state_mode = json.loads(item)["change"]
|
||||||
|
print_state()
|
||||||
|
else:
|
||||||
|
print(f"Unhandled message of type 0x{item_type:x}", file=sys.stderr, flush=True)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
Loading…
Reference in a new issue