feat(hypr): replace ags overview with hycov
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
6a880378fe
commit
540db27873
20 changed files with 242 additions and 924 deletions
|
@ -1,29 +1,9 @@
|
||||||
plugin {
|
|
||||||
touch_gestures {
|
|
||||||
# The default sensitivity is probably too low on tablet screens,
|
|
||||||
# I recommend turning it up to 4.0
|
|
||||||
sensitivity = 4.0
|
|
||||||
|
|
||||||
# must be >= 3
|
|
||||||
workspace_swipe_fingers = 3
|
|
||||||
|
|
||||||
experimental {
|
|
||||||
# send proper cancel events to windows instead of hacky touch_up events,
|
|
||||||
# NOT recommended as it crashed a few times, once it's stabilized I'll make it the default
|
|
||||||
send_cancel = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Autostart programs
|
# Autostart programs
|
||||||
exec-once = sleep 3; nextcloud --background
|
exec-once = sleep 3; nextcloud --background
|
||||||
exec-once = squeekboard
|
exec-once = squeekboard
|
||||||
exec-once = ags
|
exec-once = ags
|
||||||
exec-once = sleep 3; ags -t applauncher
|
exec-once = sleep 3; ags -t applauncher
|
||||||
|
|
||||||
## Change HandleLidSwitch to lock in logind.conf
|
|
||||||
exec-once = swayidle -w lock lock
|
|
||||||
|
|
||||||
## Special window apps
|
## Special window apps
|
||||||
exec-once = [workspace special:thunder silent] thunderbird
|
exec-once = [workspace special:thunder silent] thunderbird
|
||||||
windowrule = workspace special:thunder silent,^(thunderbird)$
|
windowrule = workspace special:thunder silent,^(thunderbird)$
|
||||||
|
@ -40,12 +20,6 @@ device:razer-razer-naga-pro-1 {
|
||||||
accel_profile = "flat"
|
accel_profile = "flat"
|
||||||
}
|
}
|
||||||
|
|
||||||
gestures {
|
|
||||||
workspace_swipe = yes
|
|
||||||
workspace_swipe_fingers = 3
|
|
||||||
workspace_swipe_cancel_ratio = 0.15
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Binds
|
# Binds
|
||||||
|
|
||||||
|
@ -58,7 +32,6 @@ bindr = CAPS, Caps_Lock, exec, ags -r 'Brightness.fetchCapsState()'
|
||||||
bindn = , Escape, exec, ags run-js 'closeAll()'
|
bindn = , Escape, exec, ags run-js 'closeAll()'
|
||||||
bind = $mainMod SHIFT, E , exec, ags -t powermenu
|
bind = $mainMod SHIFT, E , exec, ags -t powermenu
|
||||||
bind = $mainMod , D , exec, ags -t applauncher
|
bind = $mainMod , D , exec, ags -t applauncher
|
||||||
bind = ALT , Tab , exec, ags -t overview
|
|
||||||
|
|
||||||
|
|
||||||
# Cosmetic
|
# Cosmetic
|
||||||
|
|
BIN
flake.lock
BIN
flake.lock
Binary file not shown.
BIN
flake.nix
BIN
flake.nix
Binary file not shown.
|
@ -1,20 +0,0 @@
|
||||||
{...}: {
|
|
||||||
dconf.settings = {
|
|
||||||
"org/virt-manager/virt-manager/connections" = {
|
|
||||||
autoconnect = ["qemu:///system"];
|
|
||||||
uris = ["qemu:///system"];
|
|
||||||
};
|
|
||||||
|
|
||||||
"apps/seahorse/listing" = {
|
|
||||||
keyrings-selected = ["gnupg://"];
|
|
||||||
};
|
|
||||||
|
|
||||||
"org/gtk/settings/file-chooser" = {
|
|
||||||
show-hidden = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
"org/gnome/desktop/interface" = {
|
|
||||||
color-scheme = "prefer-dark";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@ import Powermenu from './ts/powermenu.ts';
|
||||||
const closeWinDelay = 800;
|
const closeWinDelay = 800;
|
||||||
|
|
||||||
|
|
||||||
// TODO: add OSD, workspace indicator / overview and current window indicator
|
// TODO: add OSD, workspace indicator and current window indicator
|
||||||
export default {
|
export default {
|
||||||
onConfigParsed: () => {
|
onConfigParsed: () => {
|
||||||
globalThis.Pointers = Pointers;
|
globalThis.Pointers = Pointers;
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
.overview {
|
|
||||||
background-color: rgba($bgfull, 0.4);
|
|
||||||
border: 2px solid $contrast-bg;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
.workspace {
|
|
||||||
padding: 4px 15px 4px 0;
|
|
||||||
border: 2px solid transparent;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: rgba(lighten($color: black, $amount: 15), 0.8);
|
|
||||||
border: 2px solid black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace .window {
|
|
||||||
background-color: $bgfull;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: 0 10px;
|
|
||||||
transition: min-width 0.2s ease-in-out,
|
|
||||||
min-height 0.2s ease-in-out,
|
|
||||||
border-color 0.2s ease-in-out,
|
|
||||||
font-size 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.normal {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
|
|
||||||
.workspace {
|
|
||||||
.window {
|
|
||||||
border: 2px solid #411C6C;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border: 2px solid purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.special {
|
|
||||||
.workspace {
|
|
||||||
.window {
|
|
||||||
border: 2px solid lighten($color: black, $amount: 20);
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border: 2px solid purple;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,7 +18,6 @@ undershoot {
|
||||||
@import "./wim-widgets/date";
|
@import "./wim-widgets/date";
|
||||||
@import "./wim-widgets/quick-settings";
|
@import "./wim-widgets/quick-settings";
|
||||||
@import "./wim-widgets/player";
|
@import "./wim-widgets/player";
|
||||||
@import "./wim-widgets/overview";
|
|
||||||
@import "./wim-widgets/applauncher";
|
@import "./wim-widgets/applauncher";
|
||||||
@import "./wim-widgets/osd";
|
@import "./wim-widgets/osd";
|
||||||
@import "./wim-widgets/osk";
|
@import "./wim-widgets/osk";
|
||||||
|
|
|
@ -1,197 +0,0 @@
|
||||||
const Hyprland = await Service.import('hyprland');
|
|
||||||
|
|
||||||
const { Icon, Revealer } = Widget;
|
|
||||||
const { timeout } = Utils;
|
|
||||||
|
|
||||||
import { WindowButton } from './dragndrop.ts';
|
|
||||||
import * as VARS from './variables.ts';
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import { Client as HyprClient } from 'types/service/hyprland.ts';
|
|
||||||
import AgsRevealer from 'types/widgets/revealer.ts';
|
|
||||||
import AgsBox from 'types/widgets/box.ts';
|
|
||||||
import AgsButton from 'types/widgets/button.ts';
|
|
||||||
import AgsIcon from 'types/widgets/icon.ts';
|
|
||||||
|
|
||||||
const scale = (size: number) => (size * VARS.SCALE) - VARS.MARGIN;
|
|
||||||
|
|
||||||
const getFontSize = (client: HyprClient) => {
|
|
||||||
const valX = scale(client.size[0]) * VARS.ICON_SCALE;
|
|
||||||
const valY = scale(client.size[1]) * VARS.ICON_SCALE;
|
|
||||||
|
|
||||||
const size = Math.min(valX, valY);
|
|
||||||
|
|
||||||
return size <= 0 ? 0.1 : size;
|
|
||||||
};
|
|
||||||
|
|
||||||
const IconStyle = (client: HyprClient) => `
|
|
||||||
min-width: ${scale(client.size[0])}px;
|
|
||||||
min-height: ${scale(client.size[1])}px;
|
|
||||||
font-size: ${getFontSize(client)}px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
|
|
||||||
const Client = (
|
|
||||||
client: HyprClient,
|
|
||||||
active: boolean,
|
|
||||||
clients: Array<HyprClient>,
|
|
||||||
box: AgsBox,
|
|
||||||
) => {
|
|
||||||
const wsName = String(client.workspace.name).replace('special:', '');
|
|
||||||
const wsId = client.workspace.id;
|
|
||||||
const addr = `address:${client.address}`;
|
|
||||||
|
|
||||||
return Revealer({
|
|
||||||
transition: 'crossfade',
|
|
||||||
reveal_child: true,
|
|
||||||
|
|
||||||
attribute: {
|
|
||||||
address: client.address,
|
|
||||||
to_destroy: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
child: WindowButton({
|
|
||||||
mainBox: box,
|
|
||||||
address: client.address,
|
|
||||||
|
|
||||||
on_secondary_click_release: () => {
|
|
||||||
Hyprland.sendMessage(`dispatch closewindow ${addr}`);
|
|
||||||
},
|
|
||||||
|
|
||||||
on_primary_click_release: () => {
|
|
||||||
if (wsId < 0) {
|
|
||||||
if (client.workspace.name === 'special') {
|
|
||||||
Hyprland.sendMessage('dispatch ' +
|
|
||||||
`movetoworkspacesilent special:${wsId},${addr}`)
|
|
||||||
.then(() => {
|
|
||||||
Hyprland.sendMessage('dispatch ' +
|
|
||||||
`togglespecialworkspace ${wsId}`)
|
|
||||||
.then(() => {
|
|
||||||
App.closeWindow('overview');
|
|
||||||
}).catch(print);
|
|
||||||
}).catch(print);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Hyprland.sendMessage('dispatch ' +
|
|
||||||
`togglespecialworkspace ${wsName}`)
|
|
||||||
.then(() => {
|
|
||||||
App.closeWindow('overview');
|
|
||||||
}).catch(print);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Close special workspace if one is opened
|
|
||||||
const activeAddress = Hyprland.active.client.address;
|
|
||||||
|
|
||||||
const currentActive = clients.find((c) => {
|
|
||||||
return c.address === activeAddress;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (currentActive && currentActive.workspace.id < 0) {
|
|
||||||
const currentSpecial = `${currentActive.workspace.name}`
|
|
||||||
.replace('special:', '');
|
|
||||||
|
|
||||||
Hyprland.sendMessage('dispatch ' +
|
|
||||||
`togglespecialworkspace ${currentSpecial}`)
|
|
||||||
.catch(print);
|
|
||||||
}
|
|
||||||
|
|
||||||
Hyprland.sendMessage(`dispatch focuswindow ${addr}`)
|
|
||||||
.then(() => {
|
|
||||||
App.closeWindow('overview');
|
|
||||||
}).catch(print);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
child: Icon({
|
|
||||||
class_name: `window ${active ? 'active' : ''}`,
|
|
||||||
css: `${IconStyle(client)} font-size: 10px;`,
|
|
||||||
icon: client.class,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateClients = (box: AgsBox) => {
|
|
||||||
Hyprland.sendMessage('j/clients').then((out) => {
|
|
||||||
let clients = JSON.parse(out) as Array<HyprClient>;
|
|
||||||
|
|
||||||
clients = clients.filter((client) => client.class);
|
|
||||||
|
|
||||||
box.attribute.workspaces.forEach(
|
|
||||||
(workspace: AgsRevealer) => {
|
|
||||||
const fixed = workspace.attribute.get_fixed();
|
|
||||||
const toRemove = fixed.get_children() as Array<AgsRevealer>;
|
|
||||||
|
|
||||||
clients.filter((client) =>
|
|
||||||
client.workspace.id === workspace.attribute.id)
|
|
||||||
.forEach((client) => {
|
|
||||||
const active =
|
|
||||||
client.address === Hyprland.active.client.address;
|
|
||||||
|
|
||||||
// TODO: see if this works on multi monitor setup
|
|
||||||
const alloc = box.get_allocation();
|
|
||||||
let monitor = box.get_display()
|
|
||||||
.get_monitor_at_point(alloc.x, alloc.y);
|
|
||||||
|
|
||||||
monitor = Hyprland.monitors.find((mon) => {
|
|
||||||
return mon.make === monitor.manufacturer &&
|
|
||||||
mon.model === monitor.model;
|
|
||||||
});
|
|
||||||
|
|
||||||
client.at[0] -= monitor.x;
|
|
||||||
client.at[1] -= monitor.y;
|
|
||||||
|
|
||||||
// Special workspaces that haven't been opened yet
|
|
||||||
// return a size of 0. We need to set them to default
|
|
||||||
// values to show the workspace properly
|
|
||||||
if (client.size[0] === 0) {
|
|
||||||
client.size[0] = VARS.DEFAULT_SPECIAL.SIZE_X;
|
|
||||||
client.size[1] = VARS.DEFAULT_SPECIAL.SIZE_Y;
|
|
||||||
client.at[0] = VARS.DEFAULT_SPECIAL.POS_X;
|
|
||||||
client.at[1] = VARS.DEFAULT_SPECIAL.POS_Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newClient = [
|
|
||||||
(fixed.get_children() as Array<AgsRevealer>)
|
|
||||||
.find((ch) =>
|
|
||||||
ch.attribute.address === client.address),
|
|
||||||
client.at[0] * VARS.SCALE,
|
|
||||||
client.at[1] * VARS.SCALE,
|
|
||||||
] as [AgsRevealer, number, number];
|
|
||||||
|
|
||||||
// If it exists already
|
|
||||||
if (newClient[0]) {
|
|
||||||
toRemove.splice(toRemove.indexOf(newClient[0]), 1);
|
|
||||||
fixed.move(...newClient);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newClient[0] = Client(client, active, clients, box);
|
|
||||||
fixed.put(...newClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a timeout here to have an animation when the icon first appears
|
|
||||||
timeout(1, () => {
|
|
||||||
((newClient[0].child as AgsButton)
|
|
||||||
.child as AgsIcon)
|
|
||||||
.class_name = `window ${active}`;
|
|
||||||
|
|
||||||
((newClient[0].child as AgsButton)
|
|
||||||
.child as AgsIcon).setCss(IconStyle(client));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
fixed.show_all();
|
|
||||||
toRemove.forEach((ch) => {
|
|
||||||
if (ch.attribute.to_destroy) {
|
|
||||||
ch.destroy();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ch.reveal_child = false;
|
|
||||||
ch.attribute.to_destroy = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}).catch(print);
|
|
||||||
};
|
|
|
@ -1,51 +0,0 @@
|
||||||
const Hyprland = await Service.import('hyprland');
|
|
||||||
|
|
||||||
const { Box } = Widget;
|
|
||||||
|
|
||||||
import * as VARS from './variables.ts';
|
|
||||||
|
|
||||||
const PADDING = 34;
|
|
||||||
const MARGIN = 9;
|
|
||||||
const DEFAULT_STYLE = `
|
|
||||||
min-width: ${VARS.SCREEN.X * VARS.SCALE}px;
|
|
||||||
min-height: ${(VARS.SCREEN.Y * VARS.SCALE) - (VARS.MARGIN / 2)}px;
|
|
||||||
border-radius: 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import AgsBox from 'types/widgets/box.ts';
|
|
||||||
import AgsRevealer from 'types/widgets/revealer.ts';
|
|
||||||
import AgsCenterBox from 'types/widgets/centerbox.ts';
|
|
||||||
import AgsEventBox from 'types/widgets/eventbox.ts';
|
|
||||||
|
|
||||||
|
|
||||||
export const Highlighter = () => Box({
|
|
||||||
vpack: 'start',
|
|
||||||
hpack: 'start',
|
|
||||||
class_name: 'workspace active',
|
|
||||||
css: DEFAULT_STYLE,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCurrentWorkspace = (main: AgsBox, highlighter: AgsBox) => {
|
|
||||||
const currentId = Hyprland.active.workspace.id;
|
|
||||||
const row = Math.floor((currentId - 1) / VARS.WORKSPACE_PER_ROW);
|
|
||||||
|
|
||||||
const rowObject = (main.children[0] as AgsBox).children[row] as AgsRevealer;
|
|
||||||
const workspaces = ((((rowObject.child as AgsCenterBox)
|
|
||||||
.center_widget as AgsEventBox)
|
|
||||||
.child as AgsBox)
|
|
||||||
.get_children() as Array<AgsRevealer>)
|
|
||||||
.filter((w) => w.reveal_child);
|
|
||||||
|
|
||||||
const currentIndex = workspaces.findIndex(
|
|
||||||
(w) => w.attribute.id === currentId,
|
|
||||||
);
|
|
||||||
const left = currentIndex * ((VARS.SCREEN.X * VARS.SCALE) + 2 + PADDING);
|
|
||||||
const height = row * ((VARS.SCREEN.Y * VARS.SCALE) + (PADDING / 2));
|
|
||||||
|
|
||||||
highlighter.setCss(`
|
|
||||||
${DEFAULT_STYLE}
|
|
||||||
margin-left: ${MARGIN + left}px;
|
|
||||||
margin-top: ${MARGIN + height}px;
|
|
||||||
`);
|
|
||||||
};
|
|
|
@ -1,122 +0,0 @@
|
||||||
const Hyprland = await Service.import('hyprland');
|
|
||||||
|
|
||||||
const { Button, EventBox } = Widget;
|
|
||||||
|
|
||||||
import Cairo from 'cairo';
|
|
||||||
const { Gtk, Gdk } = imports.gi;
|
|
||||||
|
|
||||||
import { updateClients } from './clients.ts';
|
|
||||||
|
|
||||||
const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)];
|
|
||||||
const display = Gdk.Display.get_default();
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import AgsBox from 'types/widgets/box.ts';
|
|
||||||
import AgsButton from 'types/widgets/button.ts';
|
|
||||||
import AgsRevealer from 'types/widgets/revealer.ts';
|
|
||||||
import { ButtonProps } from 'types/widgets/button.ts';
|
|
||||||
import { EventBoxProps } from 'types/widgets/eventbox.ts';
|
|
||||||
type WindowButtonType = ButtonProps & {
|
|
||||||
address: string
|
|
||||||
mainBox: AgsBox
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const createSurfaceFromWidget = (widget: AgsButton) => {
|
|
||||||
const alloc = widget.get_allocation();
|
|
||||||
const surface = new Cairo.ImageSurface(
|
|
||||||
Cairo.Format.ARGB32,
|
|
||||||
alloc.width,
|
|
||||||
alloc.height,
|
|
||||||
);
|
|
||||||
const cr = new Cairo.Context(surface);
|
|
||||||
|
|
||||||
cr.setSourceRGBA(255, 255, 255, 0);
|
|
||||||
cr.rectangle(0, 0, alloc.width, alloc.height);
|
|
||||||
cr.fill();
|
|
||||||
widget.draw(cr);
|
|
||||||
|
|
||||||
return surface;
|
|
||||||
};
|
|
||||||
|
|
||||||
let hidden = 0;
|
|
||||||
|
|
||||||
export const WorkspaceDrop = ({ ...props }: EventBoxProps) => EventBox({
|
|
||||||
...props,
|
|
||||||
setup: (self) => {
|
|
||||||
self.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY);
|
|
||||||
|
|
||||||
self.on('drag-data-received', (_, _c, _x, _y, data) => {
|
|
||||||
let id = (self.get_parent() as AgsRevealer)?.attribute.id;
|
|
||||||
|
|
||||||
if (id < -1) {
|
|
||||||
id = (self.get_parent() as AgsRevealer)?.attribute.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (id === -1) {
|
|
||||||
id = `special:${++hidden}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (id === 1000) {
|
|
||||||
id = 'empty';
|
|
||||||
}
|
|
||||||
|
|
||||||
Hyprland.sendMessage('dispatch ' +
|
|
||||||
`movetoworkspacesilent ${id},address:${data.get_text()}`)
|
|
||||||
.catch(print);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const WindowButton = ({
|
|
||||||
address,
|
|
||||||
mainBox,
|
|
||||||
...props
|
|
||||||
}: WindowButtonType) => Button({
|
|
||||||
...props,
|
|
||||||
|
|
||||||
setup: (self) => {
|
|
||||||
self.drag_source_set(
|
|
||||||
Gdk.ModifierType.BUTTON1_MASK,
|
|
||||||
TARGET,
|
|
||||||
Gdk.DragAction.COPY,
|
|
||||||
);
|
|
||||||
|
|
||||||
self
|
|
||||||
.on('drag-data-get', (_w, _c, data) => {
|
|
||||||
data.set_text(address, address.length);
|
|
||||||
})
|
|
||||||
|
|
||||||
.on('drag-begin', (_, context) => {
|
|
||||||
Gtk.drag_set_icon_surface(
|
|
||||||
context,
|
|
||||||
createSurfaceFromWidget(self),
|
|
||||||
);
|
|
||||||
(self.get_parent() as AgsRevealer)?.set_reveal_child(false);
|
|
||||||
})
|
|
||||||
|
|
||||||
.on('drag-end', () => {
|
|
||||||
self.get_parent()?.destroy();
|
|
||||||
|
|
||||||
updateClients(mainBox);
|
|
||||||
})
|
|
||||||
|
|
||||||
// OnHover
|
|
||||||
.on('enter-notify-event', () => {
|
|
||||||
if (!display) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.window.set_cursor(Gdk.Cursor.new_from_name(
|
|
||||||
display,
|
|
||||||
'pointer',
|
|
||||||
));
|
|
||||||
self.toggleClassName('hover', true);
|
|
||||||
})
|
|
||||||
|
|
||||||
// OnHoverLost
|
|
||||||
.on('leave-notify-event', () => {
|
|
||||||
self.window.set_cursor(null);
|
|
||||||
self.toggleClassName('hover', false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,151 +0,0 @@
|
||||||
const Hyprland = await Service.import('hyprland');
|
|
||||||
|
|
||||||
const { Box, Overlay, Window } = Widget;
|
|
||||||
|
|
||||||
import { WorkspaceRow, getWorkspaces, updateWorkspaces } from './workspaces.ts';
|
|
||||||
import { Highlighter, updateCurrentWorkspace } from './current-workspace.ts';
|
|
||||||
import { updateClients } from './clients.ts';
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import AgsBox from 'types/widgets/box.ts';
|
|
||||||
import AgsOverlay from 'types/widgets/overlay.ts';
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: have a 'page' for each monitor, arrows on both sides to loop through
|
|
||||||
export const Overview = () => {
|
|
||||||
const highlighter = Highlighter();
|
|
||||||
|
|
||||||
const mainBox = Box({
|
|
||||||
// Do this for scss hierarchy
|
|
||||||
class_name: 'overview',
|
|
||||||
css: 'all: unset',
|
|
||||||
|
|
||||||
vertical: true,
|
|
||||||
vpack: 'center',
|
|
||||||
hpack: 'center',
|
|
||||||
|
|
||||||
attribute: {
|
|
||||||
workspaces: [],
|
|
||||||
|
|
||||||
update: () => {
|
|
||||||
getWorkspaces(mainBox);
|
|
||||||
updateWorkspaces(mainBox);
|
|
||||||
updateClients(mainBox);
|
|
||||||
updateCurrentWorkspace(mainBox, highlighter);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
children: [
|
|
||||||
Box({
|
|
||||||
vertical: true,
|
|
||||||
children: [
|
|
||||||
WorkspaceRow('normal', 0),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
|
|
||||||
Box({
|
|
||||||
vertical: true,
|
|
||||||
children: [
|
|
||||||
WorkspaceRow('special', 0),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
|
|
||||||
setup: (self) => {
|
|
||||||
self.hook(Hyprland, () => {
|
|
||||||
if (!App.getWindow('overview')?.visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.attribute.update();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const widget = Overlay({
|
|
||||||
overlays: [highlighter, mainBox],
|
|
||||||
|
|
||||||
attribute: {
|
|
||||||
get_child: () => mainBox,
|
|
||||||
closing: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Make size of overlay big enough for content
|
|
||||||
child: Box({
|
|
||||||
class_name: 'overview',
|
|
||||||
css: `
|
|
||||||
min-height: ${mainBox.get_allocated_height()}px;
|
|
||||||
min-width: ${mainBox.get_allocated_width()}px;
|
|
||||||
`,
|
|
||||||
}),
|
|
||||||
|
|
||||||
// TODO: throttle this?
|
|
||||||
setup: (self) => {
|
|
||||||
self.on('get-child-position', (_, ch) => {
|
|
||||||
if (ch === mainBox && !self.attribute.closing) {
|
|
||||||
(self.child as AgsBox).setCss(`
|
|
||||||
transition: min-height 0.2s ease, min-width 0.2s ease;
|
|
||||||
min-height: ${mainBox.get_allocated_height()}px;
|
|
||||||
min-width: ${mainBox.get_allocated_width()}px;
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return widget;
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME: can't use PopupWindow because this is an overlay already
|
|
||||||
export default () => {
|
|
||||||
const transition_duration = 800;
|
|
||||||
const win = Window({
|
|
||||||
name: 'overview',
|
|
||||||
visible: false,
|
|
||||||
|
|
||||||
// Needs this to have space
|
|
||||||
// allocated at the start
|
|
||||||
child: Box({
|
|
||||||
css: `
|
|
||||||
min-height: 1px;
|
|
||||||
min-width: 1px;
|
|
||||||
padding: 1px;
|
|
||||||
`,
|
|
||||||
}),
|
|
||||||
|
|
||||||
attribute: { close_on_unfocus: 'none' },
|
|
||||||
|
|
||||||
setup: (self) => {
|
|
||||||
const name = 'overview';
|
|
||||||
|
|
||||||
Hyprland.sendMessage('[[BATCH]] ' +
|
|
||||||
`keyword layerrule ignorealpha[0.97],${name}; ` +
|
|
||||||
`keyword layerrule blur,${name}`);
|
|
||||||
|
|
||||||
self.hook(App, (_, currentName, isOpen) => {
|
|
||||||
if (currentName === self.name) {
|
|
||||||
if (isOpen) {
|
|
||||||
self.child = Overview();
|
|
||||||
self.show_all();
|
|
||||||
|
|
||||||
(self.child as AgsOverlay)
|
|
||||||
.attribute.get_child().attribute.update();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(self.child as AgsOverlay).attribute.closing = true;
|
|
||||||
|
|
||||||
((self.child as AgsOverlay)
|
|
||||||
.child as AgsBox).css = `
|
|
||||||
min-height: 1px;
|
|
||||||
min-width: 1px;
|
|
||||||
transition: all
|
|
||||||
${transition_duration - 10}ms ease;
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return win;
|
|
||||||
};
|
|
|
@ -1,14 +0,0 @@
|
||||||
export const SCALE = 0.11;
|
|
||||||
export const ICON_SCALE = 0.8;
|
|
||||||
export const MARGIN = 8;
|
|
||||||
export const DEFAULT_SPECIAL = {
|
|
||||||
SIZE_X: 1524,
|
|
||||||
SIZE_Y: 908,
|
|
||||||
POS_X: 197,
|
|
||||||
POS_Y: 170,
|
|
||||||
};
|
|
||||||
export const WORKSPACE_PER_ROW = 6;
|
|
||||||
export const SCREEN = {
|
|
||||||
X: 1920,
|
|
||||||
Y: 1200,
|
|
||||||
};
|
|
|
@ -1,202 +0,0 @@
|
||||||
const Hyprland = await Service.import('hyprland');
|
|
||||||
|
|
||||||
const { Revealer, CenterBox, Box, EventBox, Fixed, Label } = Widget;
|
|
||||||
|
|
||||||
import { WorkspaceDrop } from './dragndrop.ts';
|
|
||||||
import * as VARS from './variables.ts';
|
|
||||||
|
|
||||||
const EMPTY_OFFSET = 16;
|
|
||||||
const DEFAULT_STYLE = `
|
|
||||||
min-width: ${(VARS.SCREEN.X * VARS.SCALE) + EMPTY_OFFSET}px;
|
|
||||||
min-height: ${VARS.SCREEN.Y * VARS.SCALE}px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import AgsBox from 'types/widgets/box.ts';
|
|
||||||
import AgsRevealer from 'types/widgets/revealer.ts';
|
|
||||||
import AgsCenterBox from 'types/widgets/centerbox.ts';
|
|
||||||
import AgsEventBox from 'types/widgets/eventbox.ts';
|
|
||||||
|
|
||||||
|
|
||||||
export const getWorkspaces = (box: AgsBox) => {
|
|
||||||
const children = [] as Array<AgsRevealer>;
|
|
||||||
|
|
||||||
(box.children as Array<AgsBox>).forEach((type) => {
|
|
||||||
(type.children as Array<AgsRevealer>).forEach(
|
|
||||||
(row) => {
|
|
||||||
((((row.child as AgsCenterBox)
|
|
||||||
.center_widget as AgsEventBox)
|
|
||||||
.child as AgsBox)
|
|
||||||
.children as Array<AgsRevealer>)
|
|
||||||
.forEach((workspace) => {
|
|
||||||
children.push(workspace);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
box.attribute.workspaces = children.sort((a, b) => {
|
|
||||||
return a.attribute.id - b.attribute.id;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const Workspace = (id: number, name: string, normal = true) => {
|
|
||||||
// @ts-expect-error
|
|
||||||
const fixed = Fixed();
|
|
||||||
|
|
||||||
const workspace = Revealer({
|
|
||||||
transition: 'slide_right',
|
|
||||||
transition_duration: 500,
|
|
||||||
|
|
||||||
attribute: {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
get_fixed: () => fixed,
|
|
||||||
},
|
|
||||||
|
|
||||||
setup: (self) => {
|
|
||||||
if (normal) {
|
|
||||||
self.hook(Hyprland, () => {
|
|
||||||
const activeId = Hyprland.active.workspace.id;
|
|
||||||
const active = activeId === self.attribute.id;
|
|
||||||
const ws = Hyprland.getWorkspace(self.attribute.id);
|
|
||||||
|
|
||||||
self.reveal_child =
|
|
||||||
(ws?.windows && ws.windows > 0) || active;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
child: WorkspaceDrop({
|
|
||||||
child: Box({
|
|
||||||
class_name: 'workspace',
|
|
||||||
css: normal ?
|
|
||||||
|
|
||||||
DEFAULT_STYLE :
|
|
||||||
|
|
||||||
`
|
|
||||||
min-width: ${(VARS.SCREEN.X * VARS.SCALE / 2) +
|
|
||||||
EMPTY_OFFSET}px;
|
|
||||||
min-height: ${VARS.SCREEN.Y * VARS.SCALE}px;
|
|
||||||
`,
|
|
||||||
|
|
||||||
children: normal ?
|
|
||||||
|
|
||||||
[fixed] :
|
|
||||||
|
|
||||||
[
|
|
||||||
fixed,
|
|
||||||
Label({
|
|
||||||
label: ' +',
|
|
||||||
css: 'font-size: 40px;',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
return workspace;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WorkspaceRow = (class_name: string, i: number) => {
|
|
||||||
const addWorkspace = Workspace(
|
|
||||||
class_name === 'special' ? -1 : 1000,
|
|
||||||
class_name === 'special' ? 'special' : '',
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Revealer({
|
|
||||||
transition: 'slide_down',
|
|
||||||
hpack: class_name === 'special' ? 'fill' : 'start',
|
|
||||||
|
|
||||||
setup: (self) => {
|
|
||||||
self.hook(Hyprland, (rev) => {
|
|
||||||
const minId = i * VARS.WORKSPACE_PER_ROW;
|
|
||||||
const activeId = Hyprland.active.workspace.id;
|
|
||||||
|
|
||||||
const rowExists = Hyprland.workspaces.some((ws) => {
|
|
||||||
const isInRow = ws.id > minId;
|
|
||||||
const hasClients = ws.windows > 0;
|
|
||||||
const isActive = ws.id === activeId;
|
|
||||||
|
|
||||||
return isInRow && (hasClients || isActive);
|
|
||||||
});
|
|
||||||
|
|
||||||
rev.reveal_child = rowExists;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
child: CenterBox({
|
|
||||||
center_widget: EventBox({
|
|
||||||
setup: (self) => {
|
|
||||||
self.hook(Hyprland, () => {
|
|
||||||
const maxId = (i + 1) * VARS.WORKSPACE_PER_ROW;
|
|
||||||
const activeId = Hyprland.active.workspace.id;
|
|
||||||
|
|
||||||
const isSpecial = class_name === 'special';
|
|
||||||
const nextRowExists = Hyprland.workspaces.some((ws) => {
|
|
||||||
const isInNextRow = ws.id > maxId;
|
|
||||||
const hasClients = ws.windows > 0;
|
|
||||||
const isActive = ws.id === activeId;
|
|
||||||
|
|
||||||
return isInNextRow && (hasClients || isActive);
|
|
||||||
});
|
|
||||||
|
|
||||||
addWorkspace.reveal_child = isSpecial || !nextRowExists;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
child: Box({
|
|
||||||
class_name,
|
|
||||||
children: [addWorkspace],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateWorkspaces = (box: AgsBox) => {
|
|
||||||
Hyprland.workspaces.forEach((ws) => {
|
|
||||||
const currentWs = (box.attribute.workspaces as Array<AgsRevealer>).find(
|
|
||||||
(ch) => ch.attribute.id === ws.id,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!currentWs) {
|
|
||||||
let type = 0;
|
|
||||||
let rowNo = 0;
|
|
||||||
|
|
||||||
if (ws.id < 0) {
|
|
||||||
// This means it's a special workspace
|
|
||||||
type = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rowNo = Math.floor((ws.id - 1) / VARS.WORKSPACE_PER_ROW);
|
|
||||||
const wsRow = box.children[type] as AgsBox;
|
|
||||||
const wsQty = wsRow.children.length;
|
|
||||||
|
|
||||||
if (rowNo >= wsQty) {
|
|
||||||
for (let i = wsQty; i <= rowNo; ++i) {
|
|
||||||
wsRow.add(WorkspaceRow(
|
|
||||||
type ? 'special' : 'normal', i,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const row = ((((box.children[type] as AgsBox)
|
|
||||||
.children[rowNo] as AgsRevealer)
|
|
||||||
.child as AgsCenterBox)
|
|
||||||
.center_widget as AgsEventBox)
|
|
||||||
.child as AgsBox;
|
|
||||||
|
|
||||||
row.add(Workspace(ws.id, type ? ws.name : ''));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Make sure the order is correct
|
|
||||||
box.attribute.workspaces.forEach(
|
|
||||||
(workspace: AgsRevealer, i: number) => {
|
|
||||||
(workspace?.get_parent() as AgsBox)
|
|
||||||
?.reorder_child(workspace, i);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
box.show_all();
|
|
||||||
};
|
|
|
@ -7,7 +7,6 @@ import Corners from './ts/corners/main.ts';
|
||||||
import { NotifPopups, NotifCenter } from './ts/notifications/wim.ts';
|
import { NotifPopups, NotifCenter } from './ts/notifications/wim.ts';
|
||||||
import OSD from './ts/osd/main.ts';
|
import OSD from './ts/osd/main.ts';
|
||||||
import OSK from './ts/on-screen-keyboard/main.ts';
|
import OSK from './ts/on-screen-keyboard/main.ts';
|
||||||
import Overview from './ts/overview/main.ts';
|
|
||||||
import Powermenu from './ts/powermenu.ts';
|
import Powermenu from './ts/powermenu.ts';
|
||||||
import QSettings from './ts/quick-settings/main.ts';
|
import QSettings from './ts/quick-settings/main.ts';
|
||||||
|
|
||||||
|
@ -23,7 +22,6 @@ export default {
|
||||||
'notification-center': closeWinDelay,
|
'notification-center': closeWinDelay,
|
||||||
'osd': 300,
|
'osd': 300,
|
||||||
'osk': closeWinDelay,
|
'osk': closeWinDelay,
|
||||||
'overview': closeWinDelay,
|
|
||||||
'powermenu': closeWinDelay,
|
'powermenu': closeWinDelay,
|
||||||
'quick-settings': closeWinDelay,
|
'quick-settings': closeWinDelay,
|
||||||
},
|
},
|
||||||
|
@ -35,7 +33,6 @@ export default {
|
||||||
NotifCenter(),
|
NotifCenter(),
|
||||||
OSD(),
|
OSD(),
|
||||||
OSK(),
|
OSK(),
|
||||||
Overview(),
|
|
||||||
Powermenu(),
|
Powermenu(),
|
||||||
QSettings(),
|
QSettings(),
|
||||||
|
|
||||||
|
|
28
modules/dconf.nix
Normal file
28
modules/dconf.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{config, ...}: let
|
||||||
|
inherit (config.vars) mainUser;
|
||||||
|
in {
|
||||||
|
programs = {
|
||||||
|
dconf.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager.users.${mainUser} = {
|
||||||
|
dconf.settings = {
|
||||||
|
"org/virt-manager/virt-manager/connections" = {
|
||||||
|
autoconnect = ["qemu:///system"];
|
||||||
|
uris = ["qemu:///system"];
|
||||||
|
};
|
||||||
|
|
||||||
|
"apps/seahorse/listing" = {
|
||||||
|
keyrings-selected = ["gnupg://"];
|
||||||
|
};
|
||||||
|
|
||||||
|
"org/gtk/settings/file-chooser" = {
|
||||||
|
show-hidden = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
"org/gnome/desktop/interface" = {
|
||||||
|
color-scheme = "prefer-dark";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
hyprland,
|
hyprland,
|
||||||
hyprgrass,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
|
@ -10,23 +9,16 @@
|
||||||
inherit (config.vars) configDir mainUser mainMonitor;
|
inherit (config.vars) configDir mainUser mainMonitor;
|
||||||
|
|
||||||
isNvidia = config.hardware.nvidia.modesetting.enable;
|
isNvidia = config.hardware.nvidia.modesetting.enable;
|
||||||
isTouchscreen = config.hardware.sensor.iio.enable;
|
|
||||||
in {
|
in {
|
||||||
# SYSTEM CONFIG
|
# SYSTEM CONFIG
|
||||||
imports = [
|
imports = [
|
||||||
../greetd
|
../dconf.nix
|
||||||
../dolphin.nix
|
|
||||||
|
./packages.nix
|
||||||
|
./security.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
security.pam.services.swaylock = {};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
kdeconnect.enable = true;
|
|
||||||
dconf.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
gnome.gnome-keyring.enable = true;
|
|
||||||
dbus.enable = true;
|
dbus.enable = true;
|
||||||
gvfs.enable = true;
|
gvfs.enable = true;
|
||||||
};
|
};
|
||||||
|
@ -42,25 +34,16 @@ in {
|
||||||
# HOME-MANAGER CONFIG
|
# HOME-MANAGER CONFIG
|
||||||
home-manager.users.${mainUser} = {
|
home-manager.users.${mainUser} = {
|
||||||
imports = [
|
imports = [
|
||||||
../../home/foot.nix
|
|
||||||
../../home/dconf.nix
|
|
||||||
../../home/mpv
|
|
||||||
../../home/obs.nix
|
|
||||||
../../home/swaylock.nix
|
|
||||||
../../home/theme.nix
|
../../home/theme.nix
|
||||||
../../home/wofi
|
|
||||||
|
./hycov.nix
|
||||||
|
./hyprgrass.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
wayland.windowManager.hyprland = {
|
wayland.windowManager.hyprland = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = hyprland.packages.${pkgs.system}.default;
|
package = hyprland.packages.${pkgs.system}.default;
|
||||||
|
|
||||||
plugins =
|
|
||||||
[]
|
|
||||||
++ (optionals isTouchscreen [
|
|
||||||
hyprgrass.packages.${pkgs.system}.default
|
|
||||||
]);
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
env = let
|
env = let
|
||||||
gset = pkgs.gsettings-desktop-schemas;
|
gset = pkgs.gsettings-desktop-schemas;
|
||||||
|
@ -121,31 +104,15 @@ in {
|
||||||
exec-once =
|
exec-once =
|
||||||
[
|
[
|
||||||
"hyprctl setcursor Dracula-cursors 24"
|
"hyprctl setcursor Dracula-cursors 24"
|
||||||
"${pkgs.plasma5Packages.polkit-kde-agent}/libexec/polkit-kde-authentication-agent-1"
|
|
||||||
"swww init --no-cache && swww img -t none ${pkgs.dracula-theme}/wallpapers/waves.png"
|
"swww init --no-cache && swww img -t none ${pkgs.dracula-theme}/wallpapers/waves.png"
|
||||||
"wl-paste --watch cliphist store"
|
|
||||||
"${config.programs.kdeconnect.package}/libexec/kdeconnectd"
|
|
||||||
"kdeconnect-indicator"
|
|
||||||
"gnome-keyring-daemon --start --components=secrets"
|
|
||||||
]
|
]
|
||||||
++ optionals (! isNull mainMonitor)
|
++ optionals (! isNull mainMonitor)
|
||||||
["hyprctl dispatch focusmonitor ${mainMonitor}"];
|
["hyprctl dispatch focusmonitor ${mainMonitor}"];
|
||||||
|
|
||||||
windowrule = [
|
|
||||||
"noborder,^(wofi)$"
|
|
||||||
|
|
||||||
# Polkit
|
|
||||||
"float,^(org.kde.polkit-kde-authentication-agent-1)$"
|
|
||||||
"size 741 288,^(org.kde.polkit-kde-authentication-agent-1)$"
|
|
||||||
"center,^(org.kde.polkit-kde-authentication-agent-1)$"
|
|
||||||
];
|
|
||||||
|
|
||||||
"$mainMod" = "SUPER";
|
"$mainMod" = "SUPER";
|
||||||
|
|
||||||
bind = [
|
bind = [
|
||||||
# Defaults
|
# Defaults
|
||||||
"$mainMod, L, exec, lock"
|
|
||||||
"$mainMod, Q, exec, foot"
|
|
||||||
"$mainMod, F, fullscreen"
|
"$mainMod, F, fullscreen"
|
||||||
"$mainMod, C, killactive, "
|
"$mainMod, C, killactive, "
|
||||||
"$mainMod SHIFT, SPACE, togglefloating, "
|
"$mainMod SHIFT, SPACE, togglefloating, "
|
||||||
|
@ -181,12 +148,6 @@ in {
|
||||||
"$mainMod SHIFT, 9, movetoworkspace, 9"
|
"$mainMod SHIFT, 9, movetoworkspace, 9"
|
||||||
"$mainMod SHIFT, 0, movetoworkspace, 10"
|
"$mainMod SHIFT, 0, movetoworkspace, 10"
|
||||||
|
|
||||||
# Clipboard History
|
|
||||||
"$mainMod, V, exec, killall -r wofi || cliphist list | wofi --dmenu | cliphist decode | wl-copy"
|
|
||||||
|
|
||||||
",Print, exec, grim -g \"$(slurp)\" - | swappy -f -"
|
|
||||||
"$mainMod SHIFT, C, exec, wl-color-picker"
|
|
||||||
|
|
||||||
",XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle & ags -r 'showSpeaker()' &"
|
",XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle & ags -r 'showSpeaker()' &"
|
||||||
",XF86AudioMicMute, exec, pactl set-source-mute @DEFAULT_SOURCE@ toggle"
|
",XF86AudioMicMute, exec, pactl set-source-mute @DEFAULT_SOURCE@ toggle"
|
||||||
];
|
];
|
||||||
|
@ -217,52 +178,17 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# libs
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
# School
|
|
||||||
xournalpp
|
|
||||||
virt-manager
|
|
||||||
jetbrains.idea-ultimate
|
|
||||||
libreoffice-fresh # TODO: declarative conf?
|
|
||||||
hunspell
|
|
||||||
hunspellDicts.en_CA
|
|
||||||
config.customPkgs.rars-flatlaf
|
|
||||||
|
|
||||||
# Apps
|
|
||||||
thunderbird # TODO: use programs.thunderbird
|
|
||||||
spotifywm
|
|
||||||
photoqt
|
|
||||||
nextcloud-client
|
|
||||||
jellyfin-media-player
|
|
||||||
prismlauncher-qt5
|
|
||||||
|
|
||||||
/*
|
|
||||||
Discord themes for Vencord
|
|
||||||
https://markchan0225.github.io/RoundedDiscord/RoundedDiscord.theme.css
|
|
||||||
https://raw.githubusercontent.com/dracula/BetterDiscord/master/Dracula_Official.theme.css
|
|
||||||
*/
|
|
||||||
(pkgs.discord.override {
|
|
||||||
withOpenASAR = true;
|
|
||||||
withVencord = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
# tools
|
# tools
|
||||||
wl-color-picker
|
|
||||||
wl-clipboard
|
|
||||||
cliphist
|
|
||||||
grim
|
|
||||||
slurp
|
|
||||||
swappy
|
|
||||||
swayidle
|
|
||||||
bluez-tools
|
bluez-tools
|
||||||
brightnessctl
|
brightnessctl
|
||||||
pulseaudio
|
pulseaudio
|
||||||
alsa-utils
|
alsa-utils
|
||||||
gnome.seahorse
|
|
||||||
p7zip # for reshade
|
p7zip # for reshade
|
||||||
|
|
||||||
swww
|
swww
|
||||||
|
|
||||||
## libs
|
|
||||||
qt5.qtwayland
|
qt5.qtwayland
|
||||||
qt6.qtwayland
|
qt6.qtwayland
|
||||||
libayatana-appindicator
|
libayatana-appindicator
|
||||||
|
|
29
modules/hyprland/hycov.nix
Normal file
29
modules/hyprland/hycov.nix
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
hycov,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
wayland.windowManager.hyprland = {
|
||||||
|
plugins = [hycov.packages.${pkgs.system}.hycov];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
plugin = {
|
||||||
|
hycov = {
|
||||||
|
enable_alt_release_exit = 1;
|
||||||
|
overview_gappo = 60; #gaps width from screen
|
||||||
|
overview_gappi = 24; #gaps width from clients
|
||||||
|
hotarea_size = 10; #hotarea size in bottom left,10x10
|
||||||
|
enable_hotarea = 1; # enable mouse cursor hotarea
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bind = [
|
||||||
|
"ALT, tab, hycov:toggleoverview"
|
||||||
|
"ALT, left, hycov:movefocus, l"
|
||||||
|
"ALT, right, hycov:movefocus, r"
|
||||||
|
"ALT, up, hycov:movefocus, u"
|
||||||
|
"ALT, down, hycov:movefocus, d"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
41
modules/hyprland/hyprgrass.nix
Normal file
41
modules/hyprland/hyprgrass.nix
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
osConfig,
|
||||||
|
hyprgrass,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) optionalAttrs;
|
||||||
|
|
||||||
|
isTouchscreen = osConfig.hardware.sensor.iio.enable;
|
||||||
|
in
|
||||||
|
optionalAttrs isTouchscreen {
|
||||||
|
wayland.windowManager.hyprland = {
|
||||||
|
plugins = [hyprgrass.packages.${pkgs.system}.default];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
plugin = {
|
||||||
|
touch_gestures = {
|
||||||
|
# The default sensitivity is probably too low on tablet screens,
|
||||||
|
# I recommend turning it up to 4.0
|
||||||
|
sensitivity = 4.0;
|
||||||
|
|
||||||
|
# must be >= 3
|
||||||
|
workspace_swipe_fingers = 3;
|
||||||
|
|
||||||
|
experimental = {
|
||||||
|
# send proper cancel events to windows instead of hacky touch_up events,
|
||||||
|
# NOT recommended as it crashed a few times, once it's stabilized I'll make it the default
|
||||||
|
send_cancel = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gestures = {
|
||||||
|
workspace_swipe = true;
|
||||||
|
workspace_swipe_fingers = 3;
|
||||||
|
workspace_swipe_cancel_ratio = 0.15;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
83
modules/hyprland/packages.nix
Normal file
83
modules/hyprland/packages.nix
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (config.vars) mainUser;
|
||||||
|
in {
|
||||||
|
imports = [../dolphin.nix];
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
kdeconnect.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager.users.${mainUser} = {
|
||||||
|
imports = [
|
||||||
|
../../home/foot.nix
|
||||||
|
../../home/mpv
|
||||||
|
../../home/obs.nix
|
||||||
|
../../home/wofi
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
# School
|
||||||
|
xournalpp
|
||||||
|
virt-manager
|
||||||
|
libreoffice-fresh # TODO: declarative conf?
|
||||||
|
hunspell
|
||||||
|
hunspellDicts.en_CA
|
||||||
|
config.customPkgs.rars-flatlaf
|
||||||
|
|
||||||
|
# Apps
|
||||||
|
thunderbird # TODO: use programs.thunderbird
|
||||||
|
spotifywm
|
||||||
|
photoqt
|
||||||
|
nextcloud-client
|
||||||
|
jellyfin-media-player
|
||||||
|
prismlauncher-qt5
|
||||||
|
|
||||||
|
/*
|
||||||
|
Discord themes for Vencord
|
||||||
|
https://markchan0225.github.io/RoundedDiscord/RoundedDiscord.theme.css
|
||||||
|
https://raw.githubusercontent.com/dracula/BetterDiscord/master/Dracula_Official.theme.css
|
||||||
|
*/
|
||||||
|
(pkgs.discord.override {
|
||||||
|
withOpenASAR = true;
|
||||||
|
withVencord = true;
|
||||||
|
})
|
||||||
|
|
||||||
|
# tools
|
||||||
|
wl-color-picker
|
||||||
|
wl-clipboard
|
||||||
|
cliphist
|
||||||
|
grim
|
||||||
|
slurp
|
||||||
|
swappy
|
||||||
|
];
|
||||||
|
|
||||||
|
wayland.windowManager.hyprland = {
|
||||||
|
settings = {
|
||||||
|
exec-once = [
|
||||||
|
"${config.programs.kdeconnect.package}/libexec/kdeconnectd"
|
||||||
|
"kdeconnect-indicator"
|
||||||
|
|
||||||
|
"wl-paste --watch cliphist store"
|
||||||
|
];
|
||||||
|
|
||||||
|
windowrule = [
|
||||||
|
"noborder,^(wofi)$"
|
||||||
|
];
|
||||||
|
|
||||||
|
bind = [
|
||||||
|
"$mainMod, Q, exec, foot"
|
||||||
|
|
||||||
|
# Clipboard History
|
||||||
|
"$mainMod, V, exec, killall -r wofi || cliphist list | wofi --dmenu | cliphist decode | wl-copy"
|
||||||
|
|
||||||
|
",Print, exec, grim -g \"$(slurp)\" - | swappy -f -"
|
||||||
|
"$mainMod SHIFT, C, exec, wl-color-picker"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
52
modules/hyprland/security.nix
Normal file
52
modules/hyprland/security.nix
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) optionals;
|
||||||
|
inherit (config.vars) mainUser;
|
||||||
|
|
||||||
|
isLaptop = config.services.logind.lidSwitch == "lock";
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
../greetd
|
||||||
|
];
|
||||||
|
|
||||||
|
security.pam.services.swaylock = {};
|
||||||
|
services.gnome.gnome-keyring.enable = true;
|
||||||
|
|
||||||
|
home-manager.users.${mainUser} = {
|
||||||
|
imports = [
|
||||||
|
../../home/swaylock.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages = with pkgs; ([
|
||||||
|
gnome.seahorse
|
||||||
|
]
|
||||||
|
++ optionals isLaptop [
|
||||||
|
swayidle
|
||||||
|
]);
|
||||||
|
|
||||||
|
wayland.windowManager.hyprland = {
|
||||||
|
settings = {
|
||||||
|
exec-once =
|
||||||
|
[
|
||||||
|
"gnome-keyring-daemon --start --components=secrets"
|
||||||
|
"${pkgs.plasma5Packages.polkit-kde-agent}/libexec/polkit-kde-authentication-agent-1"
|
||||||
|
]
|
||||||
|
++ optionals isLaptop ["swayidle -w lock lock"];
|
||||||
|
|
||||||
|
windowrule = [
|
||||||
|
"float,^(org.kde.polkit-kde-authentication-agent-1)$"
|
||||||
|
"size 741 288,^(org.kde.polkit-kde-authentication-agent-1)$"
|
||||||
|
"center,^(org.kde.polkit-kde-authentication-agent-1)$"
|
||||||
|
];
|
||||||
|
|
||||||
|
bind = [
|
||||||
|
"$mainMod, L, exec, lock"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue