fix: Lua dispatcher compat (#112)

* fix: temporary Lua dispatcher compat for workspace dispatchers

* fix(resizer): add Lua dispatcher compat for window resize/move/float/center

* feat(theme): write current.lua for Hyprland Lua config, current.conf for hyprlang

* fix: align gen_lua format with #111

* refactor address review feedback
refactor(hypr,theme): address review feedback

- cache is_lua_config result to avoid redundant socket calls
- remove is_lua_config wrapper, rename _is_lua_config to is_lua_config
- move hypr import to top of theme.py
- use single line syntax in apply_hypr and apply_colours

* restore original specialws behavior and some formatting
This commit is contained in:
İlyas
2026-05-31 16:48:33 +03:00
committed by GitHub
parent 1ea661859d
commit ccd2712982
3 changed files with 65 additions and 7 deletions
+25 -5
View File
@@ -26,6 +26,26 @@ class Command:
self.timeout_tracker: dict[str, float] = {}
self.window_rules = self._load_window_rules()
def _make_resize_cmd(self, width: int | str, height: int | str, address: str) -> str:
if hypr.is_lua_config():
return f'dispatch hl.dsp.window.resize({{x = {width}, y = {height}, exact = true, window = "address:{address}"}})'
return f"dispatch resizewindowpixel exact {width} {height},address:{address}"
def _make_move_cmd(self, x: int, y: int, address: str) -> str:
if hypr.is_lua_config():
return f'dispatch hl.dsp.window.move({{x = {x}, y = {y}, window = "address:{address}"}})'
return f"dispatch movewindowpixel exact {x} {y},address:{address}"
def _make_float_cmd(self, address: str) -> str:
if hypr.is_lua_config():
return f'dispatch hl.dsp.window.float({{action = "toggle", window = "address:{address}"}})'
return f"dispatch togglefloating address:{address}"
def _make_center_cmd(self) -> str:
if hypr.is_lua_config():
return "dispatch hl.dsp.window.center()"
return "dispatch centerwindow"
def _load_window_rules(self) -> list[WindowRule]:
default_rules = [
WindowRule("(Bitwarden", "titleContains", "20%", "54%", ["float", "center"]),
@@ -164,8 +184,8 @@ class Command:
move_x = monitor_x + monitor_width - scaled_width - offset
move_y = monitor_y + monitor_height - scaled_height - offset
command1 = f"dispatch resizewindowpixel exact {scaled_width} {scaled_height},address:{address}"
command2 = f"dispatch movewindowpixel exact {int(move_x)} {int(move_y)},address:{address}"
command1 = self._make_resize_cmd(scaled_width, scaled_height, address)
command2 = self._make_move_cmd(int(move_x), int(move_y), address)
hypr.batch(command1, command2)
log_message(
@@ -181,16 +201,16 @@ class Command:
if "float" in actions:
window_info = self._get_window_info(window_id)
if window_info and not window_info.get("floating", False):
dispatch_commands.append(f"dispatch togglefloating address:0x{window_id}")
dispatch_commands.append(self._make_float_cmd(f"0x{window_id}"))
if "pip" in actions:
self._apply_pip_action(window_id)
return True
dispatch_commands.append(f"dispatch resizewindowpixel exact {width} {height},address:0x{window_id}")
dispatch_commands.append(self._make_resize_cmd(width, height, f"0x{window_id}"))
if "center" in actions:
dispatch_commands.append("dispatch centerwindow")
dispatch_commands.append(self._make_center_cmd())
try:
hypr.batch(*dispatch_commands)
+30
View File
@@ -7,6 +7,7 @@ socket_base = f"{os.getenv('XDG_RUNTIME_DIR')}/hypr/{os.getenv('HYPRLAND_INSTANC
socket_path = f"{socket_base}/.socket.sock"
socket2_path = f"{socket_base}/.socket2.sock"
_lua_config_cache: bool | None = None
def message(msg: str, is_json: bool = True) -> str | dict[str, Any]:
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
@@ -26,7 +27,36 @@ def message(msg: str, is_json: bool = True) -> str | dict[str, Any]:
return json.loads(resp) if is_json else resp
def is_lua_config() -> bool:
global _lua_config_cache
if _lua_config_cache is not None:
return _lua_config_cache
try:
result = message("systeminfo", is_json=False)
for line in result.splitlines():
if "configProvider:" in line:
_lua_config_cache = "lua" in line.lower()
return _lua_config_cache
_lua_config_cache = False
return False
except Exception:
_lua_config_cache = False
return False
DISPATCHER_MAP_LUA = {
"togglespecialworkspace": lambda *a: f'hl.dsp.workspace.toggle_special("{a[0]}")' if a else 'hl.dsp.workspace.toggle_special()',
"movetoworkspacesilent": lambda *a: (
f'hl.dsp.window.move({{window = "address:{a[0].split(",")[1].replace("address:", "")}", workspace = "{a[0].split(",")[0]}", follow = false}})'
),
"exec": lambda *a: 'hl.dsp.exec_cmd("' + ' '.join(a).replace('\\', '\\\\').replace('"', '\\"') + '")',
}
def dispatch(dispatcher: str, *args: str) -> bool:
if is_lua_config() and dispatcher in DISPATCHER_MAP_LUA:
lua_dispatch = DISPATCHER_MAP_LUA[dispatcher](*args)
return message(f"dispatch {lua_dispatch}", is_json=False) == "ok"
return message(f"dispatch {dispatcher} {' '.join(map(str, args))}".rstrip(), is_json=False) == "ok"
+10 -2
View File
@@ -19,6 +19,7 @@ from caelestia.utils.paths import (
user_templates_dir,
)
from caelestia.utils.scheme import get_scheme
from caelestia.utils.hypr import is_lua_config
def gen_conf(colours: dict[str, str]) -> str:
@@ -27,6 +28,12 @@ def gen_conf(colours: dict[str, str]) -> str:
conf += f"${name} = {colour}\n"
return conf
def gen_lua(colours: dict[str, str]) -> str:
lua = "return {\n"
for name, colour in colours.items():
lua += f' {name} = "{colour}",\n'
lua += "}"
return lua
def gen_scss(colours: dict[str, str]) -> str:
scss = ""
@@ -144,7 +151,8 @@ def apply_terms(sequences: str) -> None:
@log_exception
def apply_hypr(conf: str) -> None:
write_file(config_dir / "hypr/scheme/current.conf", conf)
ext = "lua" if is_lua_config() else "conf"
write_file(config_dir / f"hypr/scheme/current.{ext}", conf)
@log_exception
@@ -428,7 +436,7 @@ def apply_colours(colours: dict[str, str], mode: str) -> None:
if check("enableTerm"):
apply_terms(gen_sequences(colours))
if check("enableHypr"):
apply_hypr(gen_conf(colours))
apply_hypr(gen_lua(colours) if is_lua_config() else gen_conf(colours))
if check("enableDiscord"):
apply_discord(gen_scss(colours))
if check("enableSpicetify"):