Add multi-monitor support
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -3,12 +3,24 @@ import Launcher from './components/Launcher';
|
|||||||
import Workspace from './components/Workspaces';
|
import Workspace from './components/Workspaces';
|
||||||
import Date from './components/Date';
|
import Date from './components/Date';
|
||||||
import Systray from './components/Tray';
|
import Systray from './components/Tray';
|
||||||
|
import Hyprland from "gi://AstalHyprland";
|
||||||
|
|
||||||
const anchor = Astal.WindowAnchor.TOP
|
const anchor = Astal.WindowAnchor.TOP
|
||||||
| Astal.WindowAnchor.LEFT
|
| Astal.WindowAnchor.LEFT
|
||||||
| Astal.WindowAnchor.RIGHT;
|
| Astal.WindowAnchor.RIGHT;
|
||||||
|
|
||||||
export default (monitor: Gdk.Monitor) => <window
|
const hyprland = Hyprland.get_default();
|
||||||
|
|
||||||
|
function getHyprlandMonitor(gdkmonitor: Gdk.Monitor) {
|
||||||
|
const display = Gdk.Display.get_default()!;
|
||||||
|
const screen = display.get_default_screen();
|
||||||
|
for (let i = 0; i < display.get_n_monitors(); ++i) {
|
||||||
|
if (gdkmonitor === display.get_monitor(i))
|
||||||
|
return hyprland.get_monitor_by_name(screen.get_monitor_plug_name(i)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (monitor: Gdk.Monitor, index: number) => <window
|
||||||
className='bar'
|
className='bar'
|
||||||
gdkmonitor={monitor}
|
gdkmonitor={monitor}
|
||||||
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
||||||
@@ -17,7 +29,7 @@ export default (monitor: Gdk.Monitor) => <window
|
|||||||
<centerbox className='widgets'>
|
<centerbox className='widgets'>
|
||||||
<box hexpand halign={Gtk.Align.START}>
|
<box hexpand halign={Gtk.Align.START}>
|
||||||
<Launcher />
|
<Launcher />
|
||||||
<Workspace />
|
<Workspace monitor={getHyprlandMonitor(monitor)!} />
|
||||||
</box>
|
</box>
|
||||||
<box hexpand halign={Gtk.Align.CENTER}>
|
<box hexpand halign={Gtk.Align.CENTER}>
|
||||||
<Date />
|
<Date />
|
||||||
|
@@ -1,28 +1,23 @@
|
|||||||
import { bind, Binding, Variable } from "astal";
|
import { bind, Variable } from "astal";
|
||||||
import Hyprland from "gi://AstalHyprland";
|
import Hyprland from "gi://AstalHyprland";
|
||||||
import { range } from '../../lib';
|
import { range } from '../../lib';
|
||||||
|
|
||||||
const hyprland = Hyprland.get_default();
|
const hyprland = Hyprland.get_default();
|
||||||
|
|
||||||
const Workspace = ({ id }: { id: number }) => {
|
const Workspace = ({ workspace }: { workspace: Hyprland.Workspace }) => {
|
||||||
const className = Variable.derive(
|
const className = Variable.derive(
|
||||||
[bind(hyprland, "workspaces"), bind(hyprland, "focusedWorkspace")],
|
[bind(hyprland, "focusedWorkspace"), bind(workspace, "clients")],
|
||||||
(workspaces, focused) => {
|
(focused, clients) => {
|
||||||
const workspace = workspaces.find((w) => w.id === id);
|
if (focused.id == workspace.id) return "button active";
|
||||||
|
if (clients.length > 0) return "button occupied";
|
||||||
if (!workspace) return "button";
|
return "button";
|
||||||
|
|
||||||
const occupied = workspace.get_clients().length > 0;
|
|
||||||
const active = focused.id === id;
|
|
||||||
|
|
||||||
return `button ${active ? "active" : occupied && "occupied"}`;
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return <box vertical>
|
return <box vertical>
|
||||||
<box vexpand />
|
<box vexpand />
|
||||||
<eventbox
|
<eventbox
|
||||||
onClickRelease={() => hyprland.dispatch("workspace", `${id}`)}
|
onClickRelease={() => hyprland.dispatch("workspace", `${workspace.id}`)}
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className={className()}
|
className={className()}
|
||||||
@@ -32,13 +27,17 @@ const Workspace = ({ id }: { id: number }) => {
|
|||||||
</box>;
|
</box>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default () => <eventbox
|
export default ({ monitor }: { monitor: Hyprland.Monitor }) => {
|
||||||
className="workspaces"
|
const workspaces = hyprland.get_workspaces().filter(w => w.monitor.id == monitor.id).sort((w1, w2) => w1.id - w2.id);
|
||||||
onScroll={(_, e) => {
|
|
||||||
hyprland.dispatch("workspace", e.delta_y > 0 ? "+1" : "-1");
|
return <eventbox
|
||||||
}}
|
className="workspaces"
|
||||||
>
|
onScroll={(_, e) => {
|
||||||
<box>
|
hyprland.dispatch("workspace", e.delta_y > 0 ? "m+1" : "m-1");
|
||||||
{range(10).map((i) => <Workspace id={i} />)}
|
}}
|
||||||
</box>
|
>
|
||||||
</eventbox>
|
<box>
|
||||||
|
{workspaces.map((w) => <Workspace workspace={w} />)}
|
||||||
|
</box>
|
||||||
|
</eventbox>;
|
||||||
|
};
|
||||||
|
@@ -21,67 +21,77 @@
|
|||||||
"$mod" = "Super_L";
|
"$mod" = "Super_L";
|
||||||
"$term" = lib.meta.getExe pkgs.kitty;
|
"$term" = lib.meta.getExe pkgs.kitty;
|
||||||
|
|
||||||
bind = [
|
bind =
|
||||||
"$mod, Return, exec, $term"
|
let
|
||||||
|
bindHelper = lib.meta.getExe (
|
||||||
|
pkgs.writeShellApplication {
|
||||||
|
name = "hyprland-bind-helper";
|
||||||
|
bashOptions = [
|
||||||
|
"errexit"
|
||||||
|
"pipefail"
|
||||||
|
];
|
||||||
|
runtimeInputs = with pkgs; [ hyprland ];
|
||||||
|
text = builtins.readFile ./scripts/bind.sh;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
[
|
||||||
|
"$mod, Return, exec, $term"
|
||||||
|
|
||||||
"$mod, `, togglespecialworkspace"
|
"$mod, 1, exec, ${bindHelper} 1"
|
||||||
"$mod, 1, workspace, 1"
|
"$mod, 2, exec, ${bindHelper} 2"
|
||||||
"$mod, 2, workspace, 2"
|
"$mod, 3, exec, ${bindHelper} 3"
|
||||||
"$mod, 3, workspace, 3"
|
"$mod, 4, exec, ${bindHelper} 4"
|
||||||
"$mod, 4, workspace, 4"
|
"$mod, 5, exec, ${bindHelper} 5"
|
||||||
"$mod, 5, workspace, 5"
|
"$mod, 6, exec, ${bindHelper} 6"
|
||||||
"$mod, 6, workspace, 6"
|
"$mod, 7, exec, ${bindHelper} 7"
|
||||||
"$mod, 7, workspace, 7"
|
"$mod, 8, exec, ${bindHelper} 8"
|
||||||
"$mod, 8, workspace, 8"
|
"$mod, 9, exec, ${bindHelper} 9"
|
||||||
"$mod, 9, workspace, 9"
|
"$mod, 0, exec, ${bindHelper} 10"
|
||||||
"$mod, 0, workspace, 10"
|
|
||||||
|
|
||||||
"$mod_Shift, `, movetoworkspacesilent, special"
|
"$mod_Shift, 1, exec, ${bindHelper} 1 move"
|
||||||
"$mod_Shift, 1, movetoworkspacesilent, 1"
|
"$mod_Shift, 2, exec, ${bindHelper} 2 move"
|
||||||
"$mod_Shift, 2, movetoworkspacesilent, 2"
|
"$mod_Shift, 3, exec, ${bindHelper} 3 move"
|
||||||
"$mod_Shift, 3, movetoworkspacesilent, 3"
|
"$mod_Shift, 4, exec, ${bindHelper} 4 move"
|
||||||
"$mod_Shift, 4, movetoworkspacesilent, 4"
|
"$mod_Shift, 5, exec, ${bindHelper} 5 move"
|
||||||
"$mod_Shift, 5, movetoworkspacesilent, 5"
|
"$mod_Shift, 6, exec, ${bindHelper} 6 move"
|
||||||
"$mod_Shift, 6, movetoworkspacesilent, 6"
|
"$mod_Shift, 7, exec, ${bindHelper} 7 move"
|
||||||
"$mod_Shift, 7, movetoworkspacesilent, 7"
|
"$mod_Shift, 8, exec, ${bindHelper} 8 move"
|
||||||
"$mod_Shift, 8, movetoworkspacesilent, 8"
|
"$mod_Shift, 9, exec, ${bindHelper} 9 move"
|
||||||
"$mod_Shift, 9, movetoworkspacesilent, 9"
|
"$mod_Shift, 0, exec, ${bindHelper} 1 move0"
|
||||||
"$mod_Shift, 0, movetoworkspacesilent, 10"
|
|
||||||
|
|
||||||
"$mod_Ctrl, Space, workspaceopt, allfloat"
|
"$mod, left, movefocus, l"
|
||||||
|
"$mod, h, movefocus, l"
|
||||||
|
"$mod, down, movefocus, d"
|
||||||
|
"$mod, j, movefocus, d"
|
||||||
|
"$mod, up, movefocus, u"
|
||||||
|
"$mod, k, movefocus, u"
|
||||||
|
"$mod, right, movefocus, r"
|
||||||
|
"$mod, l, movefocus, r"
|
||||||
|
|
||||||
"$mod, left, movefocus, l"
|
"$mod_Shift, left, movewindow, l"
|
||||||
"$mod, h, movefocus, l"
|
"$mod_Shift, h, movewindow, l"
|
||||||
"$mod, down, movefocus, d"
|
"$mod_Shift, down, movewindow, d"
|
||||||
"$mod, j, movefocus, d"
|
"$mod_Shift, j, movewindow, d"
|
||||||
"$mod, up, movefocus, u"
|
"$mod_Shift, up, movewindow, u"
|
||||||
"$mod, k, movefocus, u"
|
"$mod_Shift, k, movewindow, u"
|
||||||
"$mod, right, movefocus, r"
|
"$mod_Shift, right, movewindow, r"
|
||||||
"$mod, l, movefocus, r"
|
"$mod_Shift, l, movewindow, r"
|
||||||
|
|
||||||
"$mod_Shift, left, movewindow, l"
|
"$mod, Tab, cyclenext"
|
||||||
"$mod_Shift, h, movewindow, l"
|
"$mod, Tab, bringactivetotop"
|
||||||
"$mod_Shift, down, movewindow, d"
|
"$mod_Shift, Tab, cyclenext, prev"
|
||||||
"$mod_Shift, j, movewindow, d"
|
"$mod_Shift, Tab, bringactivetotop"
|
||||||
"$mod_Shift, up, movewindow, u"
|
|
||||||
"$mod_Shift, k, movewindow, u"
|
|
||||||
"$mod_Shift, right, movewindow, r"
|
|
||||||
"$mod_Shift, l, movewindow, r"
|
|
||||||
|
|
||||||
"$mod, Tab, cyclenext"
|
"$mod, f, fullscreen, 0"
|
||||||
"$mod, Tab, bringactivetotop"
|
"$mod, m, fullscreen, 1"
|
||||||
"$mod_Shift, Tab, cyclenext, prev"
|
"$mod, p, pin"
|
||||||
"$mod_Shift, Tab, bringactivetotop"
|
"$mod, Space, togglefloating"
|
||||||
|
"$mod, Space, centerwindow"
|
||||||
|
"$mod, q, killactive"
|
||||||
|
|
||||||
"$mod, f, fullscreen, 0"
|
"Ctrl_Alt, Delete, exit"
|
||||||
"$mod, m, fullscreen, 1"
|
];
|
||||||
"$mod, p, pin"
|
|
||||||
"$mod, Space, togglefloating"
|
|
||||||
"$mod, Space, centerwindow"
|
|
||||||
"$mod, q, killactive"
|
|
||||||
|
|
||||||
"Ctrl_Alt, Delete, exit"
|
|
||||||
];
|
|
||||||
|
|
||||||
binde = [
|
binde = [
|
||||||
"$mod_Ctrl, left, resizeactive, -20 0"
|
"$mod_Ctrl, left, resizeactive, -20 0"
|
||||||
|
@@ -43,7 +43,7 @@ in
|
|||||||
systemd
|
systemd
|
||||||
];
|
];
|
||||||
runtimeEnv.SERVICES = lib.strings.concatStringsSep " " cfg.onMonitorChange.services;
|
runtimeEnv.SERVICES = lib.strings.concatStringsSep " " cfg.onMonitorChange.services;
|
||||||
text = builtins.readFile ./monitors.sh;
|
text = builtins.readFile ./scripts/monitors.sh;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} &";
|
} &";
|
||||||
|
24
hosts/common/configs/user/gui/hyprland/scripts/bind.sh
Normal file
24
hosts/common/configs/user/gui/hyprland/scripts/bind.sh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
BASE_WS="$1"
|
||||||
|
ACTION="$2"
|
||||||
|
|
||||||
|
current_ws_id="$(hyprctl -j activeworkspace | jq -r '.id')"
|
||||||
|
|
||||||
|
ws_json="$(hyprctl -j workspaces)"
|
||||||
|
max_ws_id="$(echo "$ws_json" | jq -r '[.[] | .id] | max')"
|
||||||
|
|
||||||
|
BLOCK_SIZE=10
|
||||||
|
|
||||||
|
total_blocks=$(((max_ws_id - 1) / BLOCK_SIZE + 1))
|
||||||
|
current_block=$(((current_ws_id - 1) / BLOCK_SIZE))
|
||||||
|
target_ws=$((current_block * BLOCK_SIZE + BASE_WS))
|
||||||
|
|
||||||
|
if [ "$target_ws" -eq "$current_ws_id" ]; then
|
||||||
|
next_block=$(( (current_block + 1) % total_blocks ))
|
||||||
|
target_ws=$(( next_block * BLOCK_SIZE + BASE_WS ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ACTION" = "move" ]; then
|
||||||
|
hyprctl dispatch movetoworkspacesilent "$target_ws"
|
||||||
|
else
|
||||||
|
hyprctl dispatch workspace "$target_ws"
|
||||||
|
fi
|
@@ -17,7 +17,44 @@
|
|||||||
|
|
||||||
home-manager.sharedModules = [
|
home-manager.sharedModules = [
|
||||||
{
|
{
|
||||||
wayland.windowManager.hyprland.settings.monitor = "eDP-1, 2560x1600@165, 0x0, 1.25";
|
wayland.windowManager.hyprland.settings = {
|
||||||
|
monitor = [
|
||||||
|
"eDP-1, 2560x1600@165, 0x0, 1.25"
|
||||||
|
"HDMI-A-1, 5120x1440@144, -1536x-1440, 1"
|
||||||
|
];
|
||||||
|
|
||||||
|
general = {
|
||||||
|
layout = "master";
|
||||||
|
};
|
||||||
|
|
||||||
|
master = {
|
||||||
|
slave_count_for_center_master = 0;
|
||||||
|
mfact = 0.5;
|
||||||
|
};
|
||||||
|
|
||||||
|
workspace = [
|
||||||
|
"1, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"2, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"3, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"4, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"5, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"6, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"7, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"8, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"9, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"10, monitor:eDP-1, layoutopt:orientation:left, persistent:true"
|
||||||
|
"11, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"12, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"13, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"14, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"15, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"16, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"17, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"18, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"19, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
"20, monitor:HDMI-A-1, layoutopt:orientation:center, persistent:true"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
vscode.userSettings."window.zoomLevel" = (1.25 - 1) / 0.2;
|
vscode.userSettings."window.zoomLevel" = (1.25 - 1) / 0.2;
|
||||||
|
Reference in New Issue
Block a user