diff --git a/dots/.config/hypr/hyprland.conf b/dots/.config/hypr/hyprland.conf index 632d3700c..f51e0fbcc 100644 --- a/dots/.config/hypr/hyprland.conf +++ b/dots/.config/hypr/hyprland.conf @@ -25,3 +25,6 @@ source=custom/keybinds.conf # nwg-displays support source=workspaces.conf source=monitors.conf + +# Shell overrides +source=hyprland/shellOverrides/main.conf diff --git a/dots/.config/hypr/hyprland/shellOverrides/main.conf b/dots/.config/hypr/hyprland/shellOverrides/main.conf new file mode 100644 index 000000000..e69de29bb diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml index d8ba7402b..a1d6db88e 100644 --- a/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml @@ -1,11 +1,6 @@ import QtQuick -import Quickshell import Quickshell.Io -import qs import qs.services -import qs.modules.common -import qs.modules.common.functions -import qs.modules.common.widgets QuickToggleModel { id: root @@ -14,11 +9,29 @@ QuickToggleModel { icon: "gamepad" mainAction: () => { - root.toggled = !root.toggled + root.toggled = !root.toggled; if (root.toggled) { - Quickshell.execDetached(["bash", "-c", `hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`]) + HyprlandConfig.setMany({ + "animations:enabled": 0, + "decoration:shadow:enabled": 0, + "decoration:blur:enabled": 0, + "general:gaps_in": 0, + "general:gaps_out": 0, + "general:border_size": 1, + "decoration:rounding": 0, + "general:allow_tearing": 1 + }); } else { - Quickshell.execDetached(["hyprctl", "reload"]) + HyprlandConfig.resetMany([ // + "animations:enabled", // + "decoration:shadow:enabled", // + "decoration:blur:enabled", // + "general:gaps_in", // + "general:gaps_out", // + "general:border_size", // + "decoration:rounding", // + "general:allow_tearing", // + ]); } } Process { @@ -26,7 +39,7 @@ QuickToggleModel { running: true command: ["bash", "-c", `test "$(hyprctl getoption animations:enabled -j | jq ".int")" -ne 0`] onExited: (exitCode, exitStatus) => { - root.toggled = exitCode !== 0 // Inverted because enabled = nonzero exit + root.toggled = exitCode !== 0; // Inverted because enabled = nonzero exit } } tooltipText: Translation.tr("Game mode") diff --git a/dots/.config/quickshell/ii/scripts/hyprland/hyprconfigurator.py b/dots/.config/quickshell/ii/scripts/hyprland/hyprconfigurator.py new file mode 100755 index 000000000..7d582a821 --- /dev/null +++ b/dots/.config/quickshell/ii/scripts/hyprland/hyprconfigurator.py @@ -0,0 +1,90 @@ +#!/usr/bin/env -S\_/bin/sh\_-c\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@"" +import argparse +import re +import os + +def edit_hyprland_config(file_path, set_args, reset_args): + try: + with open(file_path, 'r') as file: + lines = file.readlines() + except FileNotFoundError: + print(f"Error: File '{file_path}' not found.") + return + + set_dict = {k: v for k, v in set_args} if set_args else {} + reset_set = set(reset_args) if reset_args else set() + + new_lines = [] + found_keys = set() + + patterns = {} + for k in list(set_dict.keys()) + list(reset_set): + patterns[k] = re.compile(rf'^\s*{re.escape(k)}\s*=') + + for line in lines: + matched = False + + # Check if line matches a key to be reset + for key in reset_set: + if patterns[key].match(line): + matched = True + break + + if matched: + continue + + # Check if line matches a key to be set + for key, value in set_dict.items(): + if patterns[key].match(line): + new_line = f"{key} = {value}\n" + new_lines.append(new_line) + found_keys.add(key) + matched = True + break + + if matched: + continue + + new_lines.append(line) + + if set_dict: + for key, value in set_dict.items(): + if key not in found_keys: + if new_lines and not new_lines[-1].endswith('\n'): + new_lines[-1] += '\n' + new_lines.append(f"{key} = {value}\n") + + with open(file_path, 'w') as file: + file.writelines(new_lines) + + for key in reset_set: + print(f"Removed '{key}' from '{file_path}'") + for key, value in set_dict.items(): + print(f"Updated '{file_path}' with {key} = {value}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Edit a Hyprland config file.") + parser.add_argument("--file", default="~/.config/hypr/hyprland.conf", help="Path to the Hyprland config file (default: ~/.config/hypr/hyprland.conf).") + + parser.add_argument("--set", nargs=2, action="append", metavar=("KEY", "VALUE"), help="Set a configuration key to a value.") + parser.add_argument("--reset", action="append", metavar="KEY", help="Remove a configuration key.") + + args = parser.parse_args() + + file_path = os.path.expanduser(args.file) + + raw_set_args = args.set or [] + reset_args = args.reset or [] + + set_args = [] + for key, value in raw_set_args: + if value == "[[EMPTY]]": + reset_args.append(key) + else: + set_args.append((key, value)) + + if not set_args and not reset_args: + print("Error: Must specify at least one key to set or reset.") + else: + edit_hyprland_config(file_path, set_args, reset_args) + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/services/HyprlandConfig.qml b/dots/.config/quickshell/ii/services/HyprlandConfig.qml new file mode 100644 index 000000000..50cbe9d9b --- /dev/null +++ b/dots/.config/quickshell/ii/services/HyprlandConfig.qml @@ -0,0 +1,51 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io + +import qs.modules.common +import qs.modules.common.functions + +/** + * Configs Hyprland + */ +Singleton { + id: root + + readonly property string configuratorScriptPath: Quickshell.shellPath("scripts/hyprland/hyprconfigurator.py") + readonly property string shellOverridesPath: FileUtils.trimFileProtocol(`${Directories.config}/hypr/hyprland/shellOverrides/main.conf`) + + function set(key: string, value: var) { + Quickshell.execDetached(["bash", "-c", // + `${root.configuratorScriptPath} --file ${root.shellOverridesPath} --set "${key}" "${value}"` // + ]) + } + + function setMany(entries: var) { + let args = "" + for (let key in entries) { + args += `--set "${key}" "${entries[key]}" ` + } + Quickshell.execDetached(["bash", "-c", // + `${root.configuratorScriptPath} --file ${root.shellOverridesPath} ${args}` // + ]) + } + + function reset(key: string) { + Quickshell.execDetached(["bash", "-c", // + `${root.configuratorScriptPath} --file ${root.shellOverridesPath} --reset "${key}"` // + ]) + } + + function resetMany(keys: var) { + let args = "" + for (let i = 0; i < keys.length; i++) { + args += `--reset "${keys[i]}" ` + } + Quickshell.execDetached(["bash", "-c", // + `${root.configuratorScriptPath} --file ${root.shellOverridesPath} ${args}` // + ]) + } +}