Skip to content

Commit 325650d

Browse files
committed
fixes and ghostty bling
1 parent 4014c5f commit 325650d

File tree

8 files changed

+488
-257
lines changed

8 files changed

+488
-257
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"customPowerActionLogout": "sh -c 'if [ -n \"${XDG_SESSION_ID:-}\" ]; then loginctl terminate-session \"$XDG_SESSION_ID\"; else loginctl terminate-user \"$USER\"; fi'",
3+
"launcherLogoMode": "os",
4+
"launcherLogoCustomPath": "",
5+
"launcherLogoColorOverride": "",
6+
"launcherLogoColorInvertOnMode": false,
7+
"launcherLogoBrightness": 0.5,
8+
"launcherLogoContrast": 1,
9+
"launcherLogoSizeOffset": 0
10+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Disable bracketed paste to avoid literal ^[[200~ markers in apps that don't handle it.
2+
bracketed-paste = false
3+
custom-shader = user/share/ghostty/cursor-shader.glsl

files/system/etc/xdg/labwc/rc.xml

Lines changed: 0 additions & 94 deletions
This file was deleted.
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#!/usr/bin/python3
2+
"""
3+
Post-process the labwc menu generator output:
4+
- ensure Terminal/File Manager entries
5+
- add DMS Settings
6+
- regroup Distrobox entries under a submenu
7+
"""
8+
9+
import os
10+
import sys
11+
import xml.etree.ElementTree as ET
12+
from copy import deepcopy
13+
14+
15+
def load_env():
16+
return {
17+
"ghostty_bin": os.environ.get("GHOSTTY_BIN", "/usr/bin"),
18+
"distrobox_bin": os.environ.get("DISTROBOX_BIN", "/usr/bin"),
19+
"dbx_path": os.environ.get("DBX_PATH", "/usr/bin:/usr/local/bin"),
20+
"dms_bin": os.environ.get("DMS_BIN", "/usr/bin/dms"),
21+
"dms_path": os.environ.get("DMS_PATH", "/usr/bin"),
22+
}
23+
24+
25+
def ensure_terminal_entry(root_menu, ghostty_bin):
26+
if root_menu is None:
27+
return
28+
for child in root_menu.findall("item"):
29+
if (child.get("label") or "").strip().lower() == "terminal":
30+
return
31+
term_item = ET.Element("item", {"label": "Terminal", "icon": "utilities-terminal"})
32+
action = ET.SubElement(term_item, "action", {"name": "Execute"})
33+
cmd = ET.SubElement(action, "command")
34+
cmd.text = f"{ghostty_bin}/ghostty"
35+
root_menu.insert(0, ET.Element("separator"))
36+
root_menu.insert(0, term_item)
37+
38+
39+
def ensure_file_manager_entry(root_menu):
40+
if root_menu is None:
41+
return
42+
for child in root_menu.findall("item"):
43+
if (child.get("label") or "").strip().lower() == "file manager":
44+
return
45+
fm_item = ET.Element("item", {"label": "File Manager", "icon": "system-file-manager"})
46+
action = ET.SubElement(fm_item, "action", {"name": "Execute"})
47+
cmd = ET.SubElement(action, "command")
48+
cmd.text = "thunar"
49+
inserted = False
50+
for idx, child in enumerate(list(root_menu)):
51+
if child.tag == "item" and (child.get("label") or "").strip().lower() == "terminal":
52+
root_menu.insert(idx + 1, fm_item)
53+
inserted = True
54+
break
55+
if not inserted:
56+
root_menu.insert(0, fm_item)
57+
58+
59+
def is_distro_item(item, distrobox_bin):
60+
for action in item.findall("action"):
61+
cmd = (action.findtext("command") or "").lower()
62+
if "distrobox" in cmd or "distrobox-enter" in cmd:
63+
return True
64+
icon = (item.get("icon") or "").lower()
65+
return "distrobox" in icon
66+
67+
68+
def collect_and_prune(root_menu, distrobox_bin):
69+
distro_items = []
70+
exclude_labels = {"ikhal"}
71+
72+
def collect(elem):
73+
for child in list(elem):
74+
if child.tag == "item":
75+
label = (child.get("label") or "").strip().lower()
76+
if label in exclude_labels:
77+
elem.remove(child)
78+
continue
79+
if child.tag == "item" and is_distro_item(child, distrobox_bin):
80+
distro_items.append(deepcopy(child))
81+
elem.remove(child)
82+
elif child.tag == "menu":
83+
collect(child)
84+
85+
def prune_empty_menus(elem, keep_root=False):
86+
for child in list(elem):
87+
if child.tag == "menu":
88+
prune_empty_menus(child)
89+
if len([c for c in child if c.tag in ("item", "menu")]) == 0:
90+
elem.remove(child)
91+
92+
if root_menu is not None:
93+
collect(root_menu)
94+
prune_empty_menus(root_menu, keep_root=True)
95+
return distro_items
96+
97+
98+
def ensure_dms_settings(root, root_menu, dms_path, dms_bin):
99+
settings = root.find(".//menu[@label='Settings']") or root_menu
100+
if settings is None:
101+
return
102+
for child in settings.findall("item"):
103+
if child.get("label") == "DMS Settings":
104+
return
105+
item = ET.SubElement(settings, "item", {"label": "DMS Settings", "icon": "preferences-desktop"})
106+
action = ET.SubElement(item, "action", {"name": "Execute"})
107+
cmd = ET.SubElement(action, "command")
108+
cmd.text = (
109+
f"/bin/sh -c 'PATH={dms_path}:$PATH; export PATH; "
110+
"export XDG_CURRENT_DESKTOP=labwc; export QT_QPA_PLATFORM=wayland; "
111+
"export WAYLAND_DISPLAY=\"$${WAYLAND_DISPLAY:-wayland-0}\"; "
112+
"systemctl --user start dms.service >/dev/null || true; "
113+
f"exec {dms_bin} settings'"
114+
)
115+
116+
117+
def rewrite_distro_item(item, distrobox_bin, ghostty_bin, dbx_path):
118+
label = item.get("label") or ""
119+
if not label:
120+
return None
121+
# Skip app entries launched inside containers (we only want the containers themselves).
122+
if "(on " in label:
123+
return None
124+
original_cmd = ""
125+
for action in item.findall("action"):
126+
cmd_text = action.findtext("command")
127+
if cmd_text:
128+
original_cmd = cmd_text
129+
break
130+
if "distrobox" not in original_cmd.lower():
131+
return None
132+
# If the command chains distrobox enter with an app (contains "--"), skip it.
133+
if "--" in original_cmd:
134+
return None
135+
container = label.lower()
136+
if original_cmd:
137+
parts = original_cmd.strip().replace('"', "'").split()
138+
if parts:
139+
# Prefer explicit "-n name" if present; otherwise fall back to last arg.
140+
if "-n" in parts:
141+
try:
142+
idx = parts.index("-n")
143+
maybe = parts[idx + 1].strip("'").strip('"')
144+
if maybe:
145+
container = maybe
146+
except Exception:
147+
pass
148+
else:
149+
maybe = parts[-1].strip("'").strip('"')
150+
if maybe:
151+
container = maybe
152+
inner_cmd = original_cmd.strip() if original_cmd else f"{distrobox_bin}/distrobox enter {container}"
153+
if inner_cmd.startswith(f"{ghostty_bin}/ghostty") and "distrobox enter" in inner_cmd:
154+
tail = inner_cmd.split("distrobox enter", 1)[1].strip()
155+
tail = tail.strip("'\"")
156+
if tail:
157+
inner_cmd = f"{distrobox_bin}/distrobox enter {tail}"
158+
title_prefixed = f"Distrobox: {label}"
159+
launch = (
160+
f"/bin/sh -c \"PATH={dbx_path}; export PATH; DISABLE_AUTO_TITLE=1 "
161+
f"{ghostty_bin}/ghostty --title='{title_prefixed}' -e {inner_cmd}\""
162+
)
163+
icon = item.get("icon") or "utilities-terminal"
164+
new_item = ET.Element("item", {"label": label, "icon": icon})
165+
action = ET.SubElement(new_item, "action", {"name": "Execute"})
166+
cmd = ET.SubElement(action, "command")
167+
cmd.text = launch
168+
return new_item
169+
170+
171+
def add_distro_menu(root_menu, distro_items, distrobox_bin, ghostty_bin, dbx_path):
172+
if root_menu is None or not distro_items:
173+
return
174+
root_menu.append(ET.Element("separator"))
175+
db_menu = ET.Element("menu", {"id": "distrobox-list", "label": "Distrobox", "icon": "utilities-terminal"})
176+
for item in distro_items:
177+
new_item = rewrite_distro_item(item, distrobox_bin, ghostty_bin, dbx_path)
178+
if new_item is not None:
179+
db_menu.append(new_item)
180+
root_menu.append(db_menu)
181+
182+
183+
def main():
184+
if len(sys.argv) != 3:
185+
print("Usage: labwc-menu-postprocess.py <infile> <outfile>", file=sys.stderr)
186+
sys.exit(1)
187+
tmp, dest = sys.argv[1], sys.argv[2]
188+
env = load_env()
189+
190+
tree = ET.parse(tmp)
191+
root = tree.getroot()
192+
root_menu = root.find(".//menu[@id='root-menu']") or root.find("./menu")
193+
194+
ensure_terminal_entry(root_menu, env["ghostty_bin"])
195+
ensure_file_manager_entry(root_menu)
196+
distro_items = collect_and_prune(root_menu, env["distrobox_bin"])
197+
ensure_dms_settings(root, root_menu, env["dms_path"], env["dms_bin"])
198+
add_distro_menu(root_menu, distro_items, env["distrobox_bin"], env["ghostty_bin"], env["dbx_path"])
199+
200+
try:
201+
ET.indent(tree, space=" ")
202+
except Exception:
203+
pass
204+
tree.write(dest, encoding="utf-8", xml_declaration=True)
205+
206+
207+
if __name__ == "__main__":
208+
main()

0 commit comments

Comments
 (0)