aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJa.KooLit <jimmielovejay@gmail.com>2024-05-09 00:35:23 +0900
committerGitHub <noreply@github.com>2024-05-09 00:35:23 +0900
commit472661662b29ec932f017e44a36a63b0dc61ac38 (patch)
tree2217d9d7a5168d2eb367f0b486c6a3238b769b24
parent8e9b6f015038ae76ce68035d6aee7ff88a5be06c (diff)
parent25cbdc6a01177a5da063458438cc9ea10271ec9f (diff)
Merge pull request #247 from JaKooLit/development
Development to Main
-rw-r--r--config/ags/config.js31
-rw-r--r--config/ags/modules/.configuration/user_options.js121
-rw-r--r--config/ags/modules/.miscutils/icons.js13
-rw-r--r--config/ags/modules/.miscutils/mathfuncs.js4
-rw-r--r--config/ags/modules/.miscutils/system.js54
-rw-r--r--config/ags/modules/.widgethacks/advancedrevealers.js86
-rw-r--r--config/ags/modules/.widgethacks/popupwindow.js32
-rw-r--r--config/ags/modules/.widgetutils/clickthrough.js4
-rw-r--r--config/ags/modules/.widgetutils/cursorhover.js57
-rw-r--r--config/ags/modules/.widgetutils/keybind.js25
-rw-r--r--config/ags/modules/overview/actions.js28
-rw-r--r--config/ags/modules/overview/main.js18
-rw-r--r--config/ags/modules/overview/miscfunctions.js155
-rw-r--r--config/ags/modules/overview/overview_hyprland.js423
-rw-r--r--config/ags/modules/overview/searchbuttons.js163
-rw-r--r--config/ags/modules/overview/searchitem.js65
-rw-r--r--config/ags/modules/overview/windowcontent.js262
-rw-r--r--config/ags/user/style.css198
-rw-r--r--config/ags/user_options.js21
-rw-r--r--config/ags/variables.js21
-rw-r--r--config/hypr/UserConfigs/Startup_Apps.conf1
-rw-r--r--config/hypr/UserConfigs/UserKeybinds.conf3
-rw-r--r--config/hypr/UserConfigs/WindowRules.conf43
-rwxr-xr-xconfig/hypr/UserScripts/Weather.py14
-rwxr-xr-xconfig/hypr/UserScripts/Weather.sh4
-rw-r--r--config/hypr/configs/Keybinds.conf3
-rw-r--r--config/hypr/hyprlock.conf2
-rwxr-xr-xconfig/hypr/scripts/DarkLight.sh12
-rwxr-xr-xconfig/hypr/scripts/Refresh.sh3
-rwxr-xr-xconfig/hypr/scripts/RefreshNoWaybar.sh3
-rwxr-xr-xconfig/hypr/scripts/Wlogout.sh55
-rw-r--r--config/hypr/v2.2.11 (renamed from config/hypr/v2.2.10)0
-rw-r--r--config/rofi/config-compact.rasi13
-rw-r--r--config/rofi/config-long.rasi5
-rw-r--r--config/rofi/config-rofi-Beats.rasi2
-rw-r--r--config/rofi/config-waybar-style.rasi5
-rwxr-xr-xconfig/rofi/config.rasi13
-rwxr-xr-xconfig/rofi/resolution/1080p/config.rasi13
-rwxr-xr-x[-rw-r--r--]config/rofi/resolution/1440p/config.rasi13
-rw-r--r--config/waybar/modules2
-rw-r--r--config/waybar/style/[Catppuccin] Latte.css (renamed from config/waybar/style/Catppuccin-Latte.css)0
-rw-r--r--config/waybar/style/[Catppuccin] Mocha.css (renamed from config/waybar/style/Catppuccin-Mocha.css)0
-rw-r--r--config/waybar/style/[Colored] Translucent.css6
-rw-r--r--config/waybar/style/[Colorful] Aurora Blossom.css1
-rw-r--r--config/waybar/style/[Dark] Purpl.css (renamed from config/waybar/style/Purpl.css)0
-rw-r--r--config/waybar/style/[Extra] Crimson.css (renamed from config/waybar/style/Crimson.css)4
-rw-r--r--config/waybar/style/[Extra] Mauve.css (renamed from config/waybar/style/Mauve.css)0
-rw-r--r--config/waybar/style/[Extra] Rose Pine.css (renamed from config/waybar/style/Rose Pine.css)0
-rw-r--r--config/waybar/style/[Extra] Simple Pink.css (renamed from config/waybar/style/Simple Pink.css)0
-rw-r--r--config/waybar/style/[Pywal Bordered] Chroma Fusion Edge.css (renamed from config/waybar/style/[Bordered Pywal] Chroma Fusion Edge.css)9
-rw-r--r--config/waybar/style/[Pywal] Chroma Fusion.css9
-rw-r--r--config/waybar/style/[Pywal] Chroma Tally.css6
-rw-r--r--config/waybar/style/[Transparent] Crystal Clear.css8
53 files changed, 1948 insertions, 85 deletions
diff --git a/config/ags/config.js b/config/ags/config.js
new file mode 100644
index 00000000..278bf351
--- /dev/null
+++ b/config/ags/config.js
@@ -0,0 +1,31 @@
+"use strict";
+import GLib from 'gi://GLib';
+import App from 'resource:///com/github/Aylur/ags/app.js'
+import userOptions from './modules/.configuration/user_options.js';
+import Overview from './modules/overview/main.js';
+
+const COMPILED_STYLE_DIR = `${GLib.get_user_config_dir()}/ags/user/`
+
+async function applyStyle() {
+
+ App.resetCss();
+ App.applyCss(`${COMPILED_STYLE_DIR}/style.css`);
+ console.log('[LOG] Styles loaded')
+}
+applyStyle().catch(print);
+
+const Windows = () => [
+ Overview()
+];
+const CLOSE_ANIM_TIME = 210;
+App.config({
+ css: `${COMPILED_STYLE_DIR}/style.css`,
+ stackTraceOnError: true,
+ closeWindowDelay: {
+ 'sideright': CLOSE_ANIM_TIME,
+ 'sideleft': CLOSE_ANIM_TIME,
+ 'osk': CLOSE_ANIM_TIME,
+ },
+ windows: Windows().flat(1),
+});
+
diff --git a/config/ags/modules/.configuration/user_options.js b/config/ags/modules/.configuration/user_options.js
new file mode 100644
index 00000000..0c76a549
--- /dev/null
+++ b/config/ags/modules/.configuration/user_options.js
@@ -0,0 +1,121 @@
+
+import userOverrides from '../../user_options.js';
+
+// Defaults
+let configOptions = {
+ // General stuff
+ 'ai': {
+ 'defaultGPTProvider': "openai",
+ 'defaultTemperature': 0.9,
+ 'enhancements': true,
+ 'useHistory': true,
+ 'writingCursor': " ...", // Warning: Using weird characters can mess up Markdown rendering
+ },
+ 'animations': {
+ 'choreographyDelay': 35,
+ 'durationSmall': 110,
+ 'durationLarge': 180,
+ },
+ 'appearance': {
+ 'keyboardUseFlag': false, // Use flag emoji instead of abbreviation letters
+ },
+ 'apps': {
+ 'imageViewer': "loupe",
+ 'terminal': "foot", // This is only for shell actions
+ },
+ 'battery': {
+ 'low': 20,
+ 'critical': 10,
+ },
+ 'music': {
+ 'preferredPlayer': "plasma-browser-integration",
+ },
+ 'onScreenKeyboard': {
+ 'layout': "qwerty_full", // See modules/onscreenkeyboard/onscreenkeyboard.js for available layouts
+ },
+ 'overview': {
+ 'scale': 0.18, // Relative to screen size
+ 'numOfRows': 2,
+ 'numOfCols': 5,
+ 'wsNumScale': 0.09,
+ 'wsNumMarginScale': 0.07,
+ },
+ 'sidebar': {
+ 'imageColumns': 2,
+ 'imageBooruCount': 20,
+ 'imageAllowNsfw': false,
+ },
+ 'search': {
+ 'engineBaseUrl': "https://www.google.com/search?q=",
+ 'excludedSites': [], //add site to exclude from result. eg: "quora.com"
+ },
+ 'time': {
+ // See https://docs.gtk.org/glib/method.DateTime.format.html
+ // Here's the 12h format: "%I:%M%P"
+ // For seconds, add "%S" and set interval to 1000
+ 'format': "%H:%M",
+ 'interval': 5000,
+ 'dateFormatLong': "%A, %d/%m", // On bar
+ 'dateInterval': 5000,
+ 'dateFormat': "%d/%m", // On notif time
+ },
+ 'weather': {
+ 'city': "",
+ },
+ 'workspaces': {
+ 'shown': 10,
+ },
+ // Longer stuff
+ 'icons': {
+ substitutions: {
+ 'code-url-handler': "visual-studio-code",
+ 'Code': "visual-studio-code",
+ 'GitHub Desktop': "github-desktop",
+ 'Minecraft* 1.20.1': "minecraft",
+ 'gnome-tweaks': "org.gnome.tweaks",
+ 'pavucontrol-qt': "pavucontrol",
+ 'wps': "wps-office2019-kprometheus",
+ 'wpsoffice': "wps-office2019-kprometheus",
+ '': "image-missing",
+ }
+ },
+ 'keybinds': {
+ // Format: Mod1+Mod2+key. CaSe SeNsItIvE!
+ // Modifiers: Shift Ctrl Alt Hyper Meta
+ // See https://docs.gtk.org/gdk3/index.html#constants for the other keys (they are listed as KEY_key)
+ 'overview': {
+ 'altMoveLeft': "Ctrl+b",
+ 'altMoveRight': "Ctrl+f",
+ 'deleteToEnd': "Ctrl+k",
+ },
+ 'sidebar': {
+ 'apis': {
+ 'nextTab': "Page_Down",
+ 'prevTab': "Page_Up",
+ },
+ 'options': { // Right sidebar
+ 'nextTab': "Page_Down",
+ 'prevTab': "Page_Up",
+ },
+ 'pin': "Ctrl+p",
+ 'cycleTab': "Ctrl+Tab",
+ 'nextTab': "Ctrl+Page_Down",
+ 'prevTab': "Ctrl+Page_Up",
+ },
+ },
+}
+
+// Override defaults with user's options
+function overrideConfigRecursive(userOverrides, configOptions = {}) {
+ for (const [key, value] of Object.entries(userOverrides)) {
+ if (typeof value === 'object') {
+ overrideConfigRecursive(value, configOptions[key]);
+ } else {
+ configOptions[key] = value;
+ }
+ }
+}
+overrideConfigRecursive(userOverrides, configOptions);
+
+globalThis['userOptions'] = configOptions;
+export default configOptions; \ No newline at end of file
diff --git a/config/ags/modules/.miscutils/icons.js b/config/ags/modules/.miscutils/icons.js
new file mode 100644
index 00000000..fb1e20da
--- /dev/null
+++ b/config/ags/modules/.miscutils/icons.js
@@ -0,0 +1,13 @@
+const { Gtk } = imports.gi;
+
+export function iconExists(iconName) {
+ let iconTheme = Gtk.IconTheme.get_default();
+ return iconTheme.has_icon(iconName);
+}
+
+export function substitute(str) {
+ if(userOptions.icons.substitutions[str]) return userOptions.icons.substitutions[str];
+
+ if (!iconExists(str)) str = str.toLowerCase().replace(/\s+/g, '-'); // Turn into kebab-case
+ return str;
+} \ No newline at end of file
diff --git a/config/ags/modules/.miscutils/mathfuncs.js b/config/ags/modules/.miscutils/mathfuncs.js
new file mode 100644
index 00000000..ba1c0b59
--- /dev/null
+++ b/config/ags/modules/.miscutils/mathfuncs.js
@@ -0,0 +1,4 @@
+
+export function clamp(x, min, max) {
+ return Math.min(Math.max(x, min), max);
+} \ No newline at end of file
diff --git a/config/ags/modules/.miscutils/system.js b/config/ags/modules/.miscutils/system.js
new file mode 100644
index 00000000..ef7d15c3
--- /dev/null
+++ b/config/ags/modules/.miscutils/system.js
@@ -0,0 +1,54 @@
+const { GLib } = imports.gi;
+import Variable from 'resource:///com/github/Aylur/ags/variable.js';
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+const { execAsync, exec } = Utils;
+
+export const distroID = exec(`bash -c 'cat /etc/os-release | grep "^ID=" | cut -d "=" -f 2 | sed "s/\\"//g"'`).trim();
+export const isDebianDistro = (distroID == 'linuxmint' || distroID == 'ubuntu' || distroID == 'debian' || distroID == 'zorin' || distroID == 'popos' || distroID == 'raspbian' || distroID == 'kali');
+export const isArchDistro = (distroID == 'arch' || distroID == 'endeavouros' || distroID == 'cachyos');
+export const hasFlatpak = !!exec(`bash -c 'command -v flatpak'`);
+
+const LIGHTDARK_FILE_LOCATION = `${GLib.get_user_cache_dir()}/ags/user/colormode.txt`;
+const colorMode = Utils.exec('bash -c "sed -n \'1p\' $HOME/.cache/ags/user/colormode.txt"');
+export let darkMode = Variable(!(Utils.readFile(LIGHTDARK_FILE_LOCATION).split('\n')[0].trim() == 'light'));
+export const hasPlasmaIntegration = !!Utils.exec('bash -c "command -v plasma-browser-integration-host"');
+
+export const getDistroIcon = () => {
+ // Arches
+ if(distroID == 'arch') return 'arch-symbolic';
+ if(distroID == 'endeavouros') return 'endeavouros-symbolic';
+ if(distroID == 'cachyos') return 'cachyos-symbolic';
+ // Funny flake
+ if(distroID == 'nixos') return 'nixos-symbolic';
+ // Cool thing
+ if(distroID == 'fedora') return 'fedora-symbolic';
+ // Debians
+ if(distroID == 'linuxmint') return 'ubuntu-symbolic';
+ if(distroID == 'ubuntu') return 'ubuntu-symbolic';
+ if(distroID == 'debian') return 'debian-symbolic';
+ if(distroID == 'zorin') return 'ubuntu-symbolic';
+ if(distroID == 'popos') return 'ubuntu-symbolic';
+ if(distroID == 'raspbian') return 'debian-symbolic';
+ if(distroID == 'kali') return 'debian-symbolic';
+ return 'linux-symbolic';
+}
+
+export const getDistroName = () => {
+ // Arches
+ if(distroID == 'arch') return 'Arch Linux';
+ if(distroID == 'endeavouros') return 'EndeavourOS';
+ if(distroID == 'cachyos') return 'CachyOS';
+ // Funny flake
+ if(distroID == 'nixos') return 'NixOS';
+ // Cool thing
+ if(distroID == 'fedora') return 'Fedora';
+ // Debians
+ if(distroID == 'linuxmint') return 'Linux Mint';
+ if(distroID == 'ubuntu') return 'Ubuntu';
+ if(distroID == 'debian') return 'Debian';
+ if(distroID == 'zorin') return 'Zorin';
+ if(distroID == 'popos') return 'Pop!_OS';
+ if(distroID == 'raspbian') return 'Raspbian';
+ if(distroID == 'kali') return 'Kali Linux';
+ return 'Linux';
+}
diff --git a/config/ags/modules/.widgethacks/advancedrevealers.js b/config/ags/modules/.widgethacks/advancedrevealers.js
new file mode 100644
index 00000000..3f127931
--- /dev/null
+++ b/config/ags/modules/.widgethacks/advancedrevealers.js
@@ -0,0 +1,86 @@
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+
+const { Revealer, Scrollable } = Widget;
+
+export const MarginRevealer = ({
+ transition = 'slide_down',
+ child,
+ revealChild,
+ showClass = 'element-show', // These are for animation curve, they don't really hide
+ hideClass = 'element-hide', // Don't put margins in these classes!
+ extraSetup = () => { },
+ ...rest
+}) => {
+ const widget = Scrollable({
+ ...rest,
+ attribute: {
+ 'revealChild': true, // It'll be set to false after init if it's supposed to hide
+ 'transition': transition,
+ 'show': () => {
+ if (widget.attribute.revealChild) return;
+ widget.hscroll = 'never';
+ widget.vscroll = 'never';
+ child.toggleClassName(hideClass, false);
+ child.toggleClassName(showClass, true);
+ widget.attribute.revealChild = true;
+ child.css = 'margin: 0px;';
+ },
+ 'hide': () => {
+ if (!widget.attribute.revealChild) return;
+ child.toggleClassName(hideClass, true);
+ child.toggleClassName(showClass, false);
+ widget.attribute.revealChild = false;
+ if (widget.attribute.transition == 'slide_left')
+ child.css = `margin-right: -${child.get_allocated_width()}px;`;
+ else if (widget.attribute.transition == 'slide_right')
+ child.css = `margin-left: -${child.get_allocated_width()}px;`;
+ else if (widget.attribute.transition == 'slide_up')
+ child.css = `margin-bottom: -${child.get_allocated_height()}px;`;
+ else if (widget.attribute.transition == 'slide_down')
+ child.css = `margin-top: -${child.get_allocated_height()}px;`;
+ },
+ 'toggle': () => {
+ if (widget.attribute.revealChild) widget.attribute.hide();
+ else widget.attribute.show();
+ },
+ },
+ child: child,
+ hscroll: `${revealChild ? 'never' : 'always'}`,
+ vscroll: `${revealChild ? 'never' : 'always'}`,
+ setup: (self) => {
+ extraSetup(self);
+ }
+ });
+ child.toggleClassName(`${revealChild ? showClass : hideClass}`, true);
+ return widget;
+}
+
+// TODO: Allow reveal update. Currently this just helps at declaration
+export const DoubleRevealer = ({
+ transition1 = 'slide_right',
+ transition2 = 'slide_left',
+ duration1 = 150,
+ duration2 = 150,
+ child,
+ revealChild,
+ ...rest
+}) => {
+ const r2 = Revealer({
+ transition: transition2,
+ transitionDuration: duration2,
+ revealChild: revealChild,
+ child: child,
+ });
+ const r1 = Revealer({
+ transition: transition1,
+ transitionDuration: duration1,
+ revealChild: revealChild,
+ child: r2,
+ ...rest,
+ })
+ r1.toggleRevealChild = (value) => {
+ r1.revealChild = value;
+ r2.revealChild = value;
+ }
+ return r1;
+}
diff --git a/config/ags/modules/.widgethacks/popupwindow.js b/config/ags/modules/.widgethacks/popupwindow.js
new file mode 100644
index 00000000..26dad59c
--- /dev/null
+++ b/config/ags/modules/.widgethacks/popupwindow.js
@@ -0,0 +1,32 @@
+import App from 'resource:///com/github/Aylur/ags/app.js';
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+const { Box, Window } = Widget;
+
+
+export default ({
+ name,
+ child,
+ showClassName = "",
+ hideClassName = "",
+ ...props
+}) => {
+ return Window({
+ name,
+ visible: false,
+ layer: 'overlay',
+ ...props,
+
+ child: Box({
+ setup: (self) => {
+ self.hook(App, (self, currentName, visible) => {
+ if (currentName === name) {
+ self.toggleClassName(hideClassName, !visible);
+ }
+ }).keybind("Escape", () => App.closeWindow(name))
+ if (showClassName !== "" && hideClassName !== "")
+ self.className = `${showClassName} ${hideClassName}`;
+ },
+ child: child,
+ }),
+ });
+} \ No newline at end of file
diff --git a/config/ags/modules/.widgetutils/clickthrough.js b/config/ags/modules/.widgetutils/clickthrough.js
new file mode 100644
index 00000000..505f1412
--- /dev/null
+++ b/config/ags/modules/.widgetutils/clickthrough.js
@@ -0,0 +1,4 @@
+import Cairo from 'gi://cairo?version=1.0';
+
+export const dummyRegion = new Cairo.Region();
+export const enableClickthrough = (self) => self.input_shape_combine_region(dummyRegion); \ No newline at end of file
diff --git a/config/ags/modules/.widgetutils/cursorhover.js b/config/ags/modules/.widgetutils/cursorhover.js
new file mode 100644
index 00000000..89be913b
--- /dev/null
+++ b/config/ags/modules/.widgetutils/cursorhover.js
@@ -0,0 +1,57 @@
+const { Gdk } = imports.gi;
+
+export function setupCursorHover(button) { // Hand pointing cursor on hover
+ const display = Gdk.Display.get_default();
+ button.connect('enter-notify-event', () => {
+ const cursor = Gdk.Cursor.new_from_name(display, 'pointer');
+ button.get_window().set_cursor(cursor);
+ });
+
+ button.connect('leave-notify-event', () => {
+ const cursor = Gdk.Cursor.new_from_name(display, 'default');
+ button.get_window().set_cursor(cursor);
+ });
+
+}
+
+export function setupCursorHoverAim(button) { // Crosshair cursor on hover
+ button.connect('enter-notify-event', () => {
+ const display = Gdk.Display.get_default();
+ const cursor = Gdk.Cursor.new_from_name(display, 'crosshair');
+ button.get_window().set_cursor(cursor);
+ });
+
+ button.connect('leave-notify-event', () => {
+ const display = Gdk.Display.get_default();
+ const cursor = Gdk.Cursor.new_from_name(display, 'default');
+ button.get_window().set_cursor(cursor);
+ });
+}
+
+export function setupCursorHoverGrab(button) { // Hand ready to grab on hover
+ button.connect('enter-notify-event', () => {
+ const display = Gdk.Display.get_default();
+ const cursor = Gdk.Cursor.new_from_name(display, 'grab');
+ button.get_window().set_cursor(cursor);
+ });
+
+ button.connect('leave-notify-event', () => {
+ const display = Gdk.Display.get_default();
+ const cursor = Gdk.Cursor.new_from_name(display, 'default');
+ button.get_window().set_cursor(cursor);
+ });
+}
+
+export function setupCursorHoverInfo(button) { // "?" mark cursor on hover
+ const display = Gdk.Display.get_default();
+ button.connect('enter-notify-event', () => {
+ const cursor = Gdk.Cursor.new_from_name(display, 'help');
+ button.get_window().set_cursor(cursor);
+ });
+
+ button.connect('leave-notify-event', () => {
+ const cursor = Gdk.Cursor.new_from_name(display, 'default');
+ button.get_window().set_cursor(cursor);
+ });
+}
+
diff --git a/config/ags/modules/.widgetutils/keybind.js b/config/ags/modules/.widgetutils/keybind.js
new file mode 100644
index 00000000..eda7877b
--- /dev/null
+++ b/config/ags/modules/.widgetutils/keybind.js
@@ -0,0 +1,25 @@
+const { Gdk } = imports.gi;
+
+const MODS = {
+ 'Shift': Gdk.ModifierType.SHIFT_MASK,
+ 'Ctrl': Gdk.ModifierType.CONTROL_MASK,
+ 'Alt': Gdk.ModifierType.ALT_MASK,
+ 'Hyper': Gdk.ModifierType.HYPER_MASK,
+ 'Meta': Gdk.ModifierType.META_MASK
+}
+
+export const checkKeybind = (event, keybind) => {
+ const pressedModMask = event.get_state()[1];
+ const pressedKey = event.get_keyval()[1];
+ const keys = keybind.split('+');
+ for (let i = 0; i < keys.length; i++) {
+ if (keys[i] in MODS) {
+ if (!(pressedModMask & MODS[keys[i]])) {
+ return false;
+ }
+ } else if (pressedKey !== Gdk[`KEY_${keys[i]}`]) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/config/ags/modules/overview/actions.js b/config/ags/modules/overview/actions.js
new file mode 100644
index 00000000..766cf454
--- /dev/null
+++ b/config/ags/modules/overview/actions.js
@@ -0,0 +1,28 @@
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
+
+function moveClientToWorkspace(address, workspace) {
+ Utils.execAsync(['bash', '-c', `hyprctl dispatch movetoworkspacesilent ${workspace},address:${address} &`]);
+}
+
+export function dumpToWorkspace(from, to) {
+ if (from == to) return;
+ Hyprland.clients.forEach(client => {
+ if (client.workspace.id == from) {
+ moveClientToWorkspace(client.address, to);
+ }
+ });
+}
+
+export function swapWorkspace(workspaceA, workspaceB) {
+ if (workspaceA == workspaceB) return;
+ const clientsA = [];
+ const clientsB = [];
+ Hyprland.clients.forEach(client => {
+ if (client.workspace.id == workspaceA) clientsA.push(client.address);
+ if (client.workspace.id == workspaceB) clientsB.push(client.address);
+ });
+
+ clientsA.forEach((address) => moveClientToWorkspace(address, workspaceB));
+ clientsB.forEach((address) => moveClientToWorkspace(address, workspaceA));
+} \ No newline at end of file
diff --git a/config/ags/modules/overview/main.js b/config/ags/modules/overview/main.js
new file mode 100644
index 00000000..1f5348d9
--- /dev/null
+++ b/config/ags/modules/overview/main.js
@@ -0,0 +1,18 @@
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+import { SearchAndWindows } from "./windowcontent.js";
+import PopupWindow from '../.widgethacks/popupwindow.js';
+
+export default (id = '') => PopupWindow({
+ name: `overview${id}`,
+ exclusivity: 'ignore',
+ keymode: 'exclusive',
+ visible: false,
+ // anchor: ['middle'],
+ layer: 'overlay',
+ child: Widget.Box({
+ vertical: true,
+ children: [
+ SearchAndWindows(),
+ ]
+ }),
+})
diff --git a/config/ags/modules/overview/miscfunctions.js b/config/ags/modules/overview/miscfunctions.js
new file mode 100644
index 00000000..187ee6ec
--- /dev/null
+++ b/config/ags/modules/overview/miscfunctions.js
@@ -0,0 +1,155 @@
+const { Gio, GLib } = imports.gi;
+import App from 'resource:///com/github/Aylur/ags/app.js';
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+const { execAsync, exec } = Utils;
+// import Todo from "../../services/todo.js";
+import { darkMode } from '../.miscutils/system.js';
+
+export function hasUnterminatedBackslash(inputString) {
+ // Use a regular expression to match a trailing odd number of backslashes
+ const regex = /\\+$/;
+ return regex.test(inputString);
+}
+
+export function launchCustomCommand(command) {
+ const args = command.toLowerCase().split(' ');
+ if (args[0] == '>raw') { // Mouse raw input
+ Utils.execAsync('hyprctl -j getoption input:accel_profile')
+ .then((output) => {
+ const value = JSON.parse(output)["str"].trim();
+ if (value != "[[EMPTY]]" && value != "") {
+ execAsync(['bash', '-c', `hyprctl keyword input:accel_profile '[[EMPTY]]'`]).catch(print);
+ }
+ else {
+ execAsync(['bash', '-c', `hyprctl keyword input:accel_profile flat`]).catch(print);
+ }
+ })
+ }
+ else if (args[0] == '>img') { // Change wallpaper
+ execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchwall.sh`, `&`]).catch(print);
+ }
+ else if (args[0] == '>color') { // Generate colorscheme from color picker
+ execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchcolor.sh --pick`, `&`]).catch(print);
+ }
+ else if (args[0] == '>light') { // Light mode
+ darkMode.value = false;
+ execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && sed -i "1s/.*/light/" ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`])
+ .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`]))
+ .catch(print);
+ }
+ else if (args[0] == '>dark') { // Dark mode
+ darkMode.value = true;
+ execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && sed -i "1s/.*/dark/" ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`])
+ .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`]))
+ .catch(print);
+ }
+ else if (args[0] == '>badapple') { // Black and white
+ execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && sed -i "3s/.*/monochrome/" ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`])
+ .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`]))
+ .catch(print);
+ }
+ else if (args[0] == '>material') { // Use material colors
+ execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "material" > ${GLib.get_user_cache_dir()}/ags/user/colorbackend.txt`]).catch(print)
+ .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchwall.sh --noswitch`]).catch(print))
+ .catch(print);
+ }
+ else if (args[0] == '>pywal') { // Use Pywal (ik it looks shit but I'm not removing)
+ execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "pywal" > ${GLib.get_user_cache_dir()}/ags/user/colorbackend.txt`]).catch(print)
+ .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchwall.sh --noswitch`]).catch(print))
+ .catch(print);
+ }
+ else if (args[0] == '>todo') { // Todo
+ Todo.add(args.slice(1).join(' '));
+ }
+ else if (args[0] == '>shutdown') { // Shut down
+ execAsync([`bash`, `-c`, `systemctl poweroff || loginctl poweroff`]).catch(print);
+ }
+ else if (args[0] == '>reboot') { // Reboot
+ execAsync([`bash`, `-c`, `systemctl reboot || loginctl reboot`]).catch(print);
+ }
+ else if (args[0] == '>sleep') { // Sleep
+ execAsync([`bash`, `-c`, `systemctl suspend || loginctl suspend`]).catch(print);
+ }
+ else if (args[0] == '>logout') { // Log out
+ execAsync([`bash`, `-c`, `pkill Hyprland || pkill sway`]).catch(print);
+ }
+}
+
+export function execAndClose(command, terminal) {
+ App.closeWindow('overview');
+ if (terminal) {
+ execAsync([`bash`, `-c`, `${userOptions.apps.terminal} fish -C "${command}"`, `&`]).catch(print);
+ }
+ else
+ execAsync(command).catch(print);
+}
+
+export function couldBeMath(str) {
+ const regex = /^[0-9.+*/-]/;
+ return regex.test(str);
+}
+
+export function expandTilde(path) {
+ if (path.startsWith('~')) {
+ return GLib.get_home_dir() + path.slice(1);
+ } else {
+ return path;
+ }
+}
+
+function getFileIcon(fileInfo) {
+ let icon = fileInfo.get_icon();
+ if (icon) {
+ // Get the icon's name
+ return icon.get_names()[0];
+ } else {
+ // Default icon for files
+ return 'text-x-generic';
+ }
+}
+
+export function ls({ path = '~', silent = false }) {
+ let contents = [];
+ try {
+ let expandedPath = expandTilde(path);
+ if (expandedPath.endsWith('/'))
+ expandedPath = expandedPath.slice(0, -1);
+ let folder = Gio.File.new_for_path(expandedPath);
+
+ let enumerator = folder.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
+ let fileInfo;
+ while ((fileInfo = enumerator.next_file(null)) !== null) {
+ let fileName = fileInfo.get_display_name();
+ let fileType = fileInfo.get_file_type();
+
+ let item = {
+ parentPath: expandedPath,
+ name: fileName,
+ type: fileType === Gio.FileType.DIRECTORY ? 'folder' : 'file',
+ icon: getFileIcon(fileInfo),
+ };
+
+ // Add file extension for files
+ if (fileType === Gio.FileType.REGULAR) {
+ let fileExtension = fileName.split('.').pop();
+ item.type = `${fileExtension}`;
+ }
+
+ contents.push(item);
+ contents.sort((a, b) => {
+ const aIsFolder = a.type.startsWith('folder');
+ const bIsFolder = b.type.startsWith('folder');
+ if (aIsFolder && !bIsFolder) {
+ return -1;
+ } else if (!aIsFolder && bIsFolder) {
+ return 1;
+ } else {
+ return a.name.localeCompare(b.name); // Sort alphabetically within folders and files
+ }
+ });
+ }
+ } catch (e) {
+ if (!silent) console.log(e);
+ }
+ return contents;
+}
diff --git a/config/ags/modules/overview/overview_hyprland.js b/config/ags/modules/overview/overview_hyprland.js
new file mode 100644
index 00000000..034d6c81
--- /dev/null
+++ b/config/ags/modules/overview/overview_hyprland.js
@@ -0,0 +1,423 @@
+// TODO
+// - Make client destroy/create not destroy and recreate the whole thing
+// - Active ws hook optimization: only update when moving to next group
+//
+const { Gdk, Gtk } = imports.gi;
+const { Gravity } = imports.gi.Gdk;
+import { SCREEN_HEIGHT, SCREEN_WIDTH } from '../../variables.js';
+import App from 'resource:///com/github/Aylur/ags/app.js';
+import Variable from 'resource:///com/github/Aylur/ags/variable.js';
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+
+import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
+const { execAsync, exec } = Utils;
+import { setupCursorHoverGrab } from '../.widgetutils/cursorhover.js';
+import { dumpToWorkspace, swapWorkspace } from "./actions.js";
+import { substitute } from "../.miscutils/icons.js";
+
+const NUM_OF_WORKSPACES_SHOWN = userOptions.overview.numOfCols * userOptions.overview.numOfRows;
+const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)];
+const POPUP_CLOSE_TIME = 100; // ms
+
+const overviewTick = Variable(false);
+
+export default () => {
+ const clientMap = new Map();
+ let workspaceGroup = 0;
+ const ContextMenuWorkspaceArray = ({ label, actionFunc, thisWorkspace }) => Widget.MenuItem({
+ label: `${label}`,
+ setup: (menuItem) => {
+ let submenu = new Gtk.Menu();
+ submenu.className = 'menu';
+
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ const startWorkspace = offset + 1;
+ const endWorkspace = startWorkspace + NUM_OF_WORKSPACES_SHOWN - 1;
+ for (let i = startWorkspace; i <= endWorkspace; i++) {
+ let button = new Gtk.MenuItem({
+ label: `Workspace ${i}`
+ });
+ button.connect("activate", () => {
+ // execAsync([`${onClickBinary}`, `${thisWorkspace}`, `${i}`]).catch(print);
+ actionFunc(thisWorkspace, i);
+ overviewTick.setValue(!overviewTick.value);
+ });
+ submenu.append(button);
+ }
+ menuItem.set_reserve_indicator(true);
+ menuItem.set_submenu(submenu);
+ }
+ })
+
+ const Window = ({ address, at: [x, y], size: [w, h], workspace: { id, name }, class: c, title, xwayland }, screenCoords) => {
+ const revealInfoCondition = (Math.min(w, h) * userOptions.overview.scale > 70);
+ if (w <= 0 || h <= 0 || (c === '' && title === '') || c.endsWith('-dropterm')) return null;
+ // Non-primary monitors
+ if (screenCoords.x != 0) x -= screenCoords.x;
+ if (screenCoords.y != 0) y -= screenCoords.y;
+ // Other offscreen adjustments
+ if (x + w <= 0) x += (Math.floor(x / SCREEN_WIDTH) * SCREEN_WIDTH);
+ else if (x < 0) { w = x + w; x = 0; }
+ if (y + h <= 0) x += (Math.floor(y / SCREEN_HEIGHT) * SCREEN_HEIGHT);
+ else if (y < 0) { h = y + h; y = 0; }
+ // Truncate if offscreen
+ if (x + w > SCREEN_WIDTH) w = SCREEN_WIDTH - x;
+ if (y + h > SCREEN_HEIGHT) h = SCREEN_HEIGHT - y;
+
+ const appIcon = Widget.Icon({
+ icon: substitute(c),
+ size: Math.min(w, h) * userOptions.overview.scale / 2.5,
+ });
+ return Widget.Button({
+ attribute: {
+ address, x, y, w, h, ws: id,
+ updateIconSize: (self) => {
+ appIcon.size = Math.min(self.attribute.w, self.attribute.h) * userOptions.overview.scale / 2.5;
+ },
+ },
+ className: 'overview-tasks-window',
+ hpack: 'start',
+ vpack: 'start',
+ css: `
+ margin-left: ${Math.round(x * userOptions.overview.scale)}px;
+ margin-top: ${Math.round(y * userOptions.overview.scale)}px;
+ margin-right: -${Math.round((x + w) * userOptions.overview.scale)}px;
+ margin-bottom: -${Math.round((y + h) * userOptions.overview.scale)}px;
+ `,
+ onClicked: (self) => {
+ App.closeWindow('overview');
+ Utils.timeout(POPUP_CLOSE_TIME, () => Hyprland.messageAsync(`dispatch focuswindow address:${address}`));
+ },
+ onMiddleClickRelease: () => Hyprland.messageAsync(`dispatch closewindow address:${address}`),
+ onSecondaryClick: (button) => {
+ button.toggleClassName('overview-tasks-window-selected', true);
+ const menu = Widget.Menu({
+ className: 'menu',
+ children: [
+ Widget.MenuItem({
+ child: Widget.Label({
+ xalign: 0,
+ label: "Close (Middle-click)",
+ }),
+ onActivate: () => Hyprland.messageAsync(`dispatch closewindow address:${address}`),
+ }),
+ ContextMenuWorkspaceArray({
+ label: "Dump windows to workspace",
+ actionFunc: dumpToWorkspace,
+ thisWorkspace: Number(id)
+ }),
+ ContextMenuWorkspaceArray({
+ label: "Swap windows with workspace",
+ actionFunc: swapWorkspace,
+ thisWorkspace: Number(id)
+ }),
+ ],
+ });
+ menu.connect("deactivate", () => {
+ button.toggleClassName('overview-tasks-window-selected', false);
+ })
+ menu.connect("selection-done", () => {
+ button.toggleClassName('overview-tasks-window-selected', false);
+ })
+ menu.popup_at_widget(button.get_parent(), Gravity.SOUTH, Gravity.NORTH, null); // Show menu below the button
+ button.connect("destroy", () => menu.destroy());
+ },
+ child: Widget.Box({
+ homogeneous: true,
+ child: Widget.Box({
+ vertical: true,
+ vpack: 'center',
+ className: 'spacing-v-5',
+ children: [
+ appIcon,
+ // TODO: Add xwayland tag instead of just having italics
+ Widget.Revealer({
+ transition: 'slide_down',
+ revealChild: revealInfoCondition,
+ child: Widget.Label({
+ maxWidthChars: 10, // Doesn't matter what number
+ truncate: 'end',
+ className: `${xwayland ? 'txt txt-italic' : 'txt'}`,
+ css: `
+ font-size: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * userOptions.overview.scale / 14.6}px;
+ margin: 0px ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * userOptions.overview.scale / 10}px;
+ `,
+ // If the title is too short, include the class
+ label: (title.length <= 1 ? `${c}: ${title}` : title),
+ })
+ })
+ ]
+ })
+ }),
+ tooltipText: `${c}: ${title}`,
+ setup: (button) => {
+ setupCursorHoverGrab(button);
+
+ button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.MOVE);
+ button.drag_source_set_icon_name(substitute(c));
+ // button.drag_source_set_icon_gicon(icon);
+
+ button.connect('drag-begin', (button) => { // On drag start, add the dragging class
+ button.toggleClassName('overview-tasks-window-dragging', true);
+ });
+ button.connect('drag-data-get', (_w, _c, data) => { // On drag finish, give address
+ data.set_text(address, address.length);
+ button.toggleClassName('overview-tasks-window-dragging', false);
+ });
+ },
+ });
+ }
+
+ const Workspace = (index) => {
+ // const fixed = Widget.Fixed({
+ // attribute: {
+ // put: (widget, x, y) => {
+ // fixed.put(widget, x, y);
+ // },
+ // move: (widget, x, y) => {
+ // fixed.move(widget, x, y);
+ // },
+ // }
+ // });
+ const fixed = Widget.Box({
+ attribute: {
+ put: (widget, x, y) => {
+ if (!widget.attribute) return;
+ // Note: x and y are already multiplied by userOptions.overview.scale
+ const newCss = `
+ margin-left: ${Math.round(x)}px;
+ margin-top: ${Math.round(y)}px;
+ margin-right: -${Math.round(x + (widget.attribute.w * userOptions.overview.scale))}px;
+ margin-bottom: -${Math.round(y + (widget.attribute.h * userOptions.overview.scale))}px;
+ `;
+ widget.css = newCss;
+ fixed.pack_start(widget, false, false, 0);
+ },
+ move: (widget, x, y) => {
+ if (!widget) return;
+ if (!widget.attribute) return;
+ // Note: x and y are already multiplied by userOptions.overview.scale
+ const newCss = `
+ margin-left: ${Math.round(x)}px;
+ margin-top: ${Math.round(y)}px;
+ margin-right: -${Math.round(x + (widget.attribute.w * userOptions.overview.scale))}px;
+ margin-bottom: -${Math.round(y + (widget.attribute.h * userOptions.overview.scale))}px;
+ `;
+ widget.css = newCss;
+ },
+ }
+ })
+ const WorkspaceNumber = ({ index, ...rest }) => Widget.Label({
+ className: 'overview-tasks-workspace-number',
+ label: `${index}`,
+ css: `
+ margin: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * userOptions.overview.scale * userOptions.overview.wsNumMarginScale}px;
+ font-size: ${SCREEN_HEIGHT * userOptions.overview.scale * userOptions.overview.wsNumScale}px;
+ `,
+ setup: (self) => self.hook(Hyprland.active.workspace, (self) => {
+ // Update when going to new ws group
+ const currentGroup = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN);
+ self.label = `${currentGroup * NUM_OF_WORKSPACES_SHOWN + index}`;
+ }),
+ ...rest,
+ })
+ const widget = Widget.Box({
+ className: 'overview-tasks-workspace',
+ vpack: 'center',
+ css: `
+ min-width: ${SCREEN_WIDTH * userOptions.overview.scale}px;
+ min-height: ${SCREEN_HEIGHT * userOptions.overview.scale}px;
+ `,
+ children: [Widget.EventBox({
+ hexpand: true,
+ vexpand: true,
+ onPrimaryClick: () => {
+ App.closeWindow('overview');
+ Utils.timeout(POPUP_CLOSE_TIME, () => Hyprland.messageAsync(`dispatch workspace ${index}`));
+ },
+ setup: (eventbox) => {
+ eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY);
+ eventbox.connect('drag-data-received', (_w, _c, _x, _y, data) => {
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ Hyprland.messageAsync(`dispatch movetoworkspacesilent ${index + offset},address:${data.get_text()}`)
+ overviewTick.setValue(!overviewTick.value);
+ });
+ },
+ child: Widget.Overlay({
+ child: Widget.Box({}),
+ overlays: [
+ WorkspaceNumber({ index: index, hpack: 'start', vpack: 'start' }),
+ fixed
+ ]
+ }),
+ })],
+ });
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ fixed.attribute.put(WorkspaceNumber(offset + index), 0, 0);
+ widget.clear = () => {
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ clientMap.forEach((client, address) => {
+ if (!client) return;
+ if ((client.attribute.ws <= offset || client.attribute.ws > offset + NUM_OF_WORKSPACES_SHOWN) ||
+ (client.attribute.ws == offset + index)) {
+ client.destroy();
+ client = null;
+ clientMap.delete(address);
+ }
+ });
+ }
+ widget.set = (clientJson, screenCoords) => {
+ let c = clientMap.get(clientJson.address);
+ if (c) {
+ if (c.attribute?.ws !== clientJson.workspace.id) {
+ c.destroy();
+ c = null;
+ clientMap.delete(clientJson.address);
+ }
+ else if (c) {
+ c.attribute.w = clientJson.size[0];
+ c.attribute.h = clientJson.size[1];
+ c.attribute.updateIconSize(c);
+ fixed.attribute.move(c,
+ Math.max(0, clientJson.at[0] * userOptions.overview.scale),
+ Math.max(0, clientJson.at[1] * userOptions.overview.scale)
+ );
+ return;
+ }
+ }
+ const newWindow = Window(clientJson, screenCoords);
+ if (newWindow === null) return;
+ // clientMap.set(clientJson.address, newWindow);
+ fixed.attribute.put(newWindow,
+ Math.max(0, newWindow.attribute.x * userOptions.overview.scale),
+ Math.max(0, newWindow.attribute.y * userOptions.overview.scale)
+ );
+ clientMap.set(clientJson.address, newWindow);
+ };
+ widget.unset = (clientAddress) => {
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ let c = clientMap.get(clientAddress);
+ if (!c) return;
+ c.destroy();
+ c = null;
+ clientMap.delete(clientAddress);
+ };
+ widget.show = () => {
+ fixed.show_all();
+ }
+ return widget;
+ };
+
+ const arr = (s, n) => {
+ const array = [];
+ for (let i = 0; i < n; i++)
+ array.push(s + i);
+
+ return array;
+ };
+
+ const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) => Widget.Box({
+ children: arr(startWorkspace, workspaces).map(Workspace),
+ attribute: {
+ monitorMap: [],
+ getMonitorMap: (box) => {
+ execAsync('hyprctl -j monitors').then(monitors => {
+ box.attribute.monitorMap = JSON.parse(monitors).reduce((acc, item) => {
+ acc[item.id] = { x: item.x, y: item.y };
+ return acc;
+ }, {});
+ });
+ },
+ update: (box) => {
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ if (!App.getWindow(windowName).visible) return;
+ Hyprland.messageAsync('j/clients').then(clients => {
+ const allClients = JSON.parse(clients);
+ const kids = box.get_children();
+ kids.forEach(kid => kid.clear());
+ for (let i = 0; i < allClients.length; i++) {
+ const client = allClients[i];
+ const childID = client.workspace.id - (offset + startWorkspace);
+ if (offset + startWorkspace <= client.workspace.id &&
+ client.workspace.id <= offset + startWorkspace + workspaces) {
+ const screenCoords = box.attribute.monitorMap[client.monitor];
+ if (kids[childID]) {
+ kids[childID].set(client, screenCoords);
+ }
+ continue;
+ }
+ }
+ kids.forEach(kid => kid.show());
+ }).catch(print);
+ },
+ updateWorkspace: (box, id) => {
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ if (!( // Not in range, ignore
+ offset + startWorkspace <= id &&
+ id <= offset + startWorkspace + workspaces
+ )) return;
+ // if (!App.getWindow(windowName).visible) return;
+ Hyprland.messageAsync('j/clients').then(clients => {
+ const allClients = JSON.parse(clients);
+ const kids = box.get_children();
+ for (let i = 0; i < allClients.length; i++) {
+ const client = allClients[i];
+ if (client.workspace.id != id) continue;
+ const screenCoords = box.attribute.monitorMap[client.monitor];
+ kids[id - (offset + startWorkspace)]?.set(client, screenCoords);
+ }
+ kids[id - (offset + startWorkspace)]?.show();
+ }).catch(print);
+ },
+ },
+ setup: (box) => {
+ box.attribute.getMonitorMap(box);
+ box
+ .hook(overviewTick, (box) => box.attribute.update(box))
+ .hook(Hyprland, (box, clientAddress) => {
+ const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN;
+ const kids = box.get_children();
+ const client = Hyprland.getClient(clientAddress);
+ if (!client) return;
+ const id = client.workspace.id;
+
+ box.attribute.updateWorkspace(box, id);
+ kids[id - (offset + startWorkspace)]?.unset(clientAddress);
+ }, 'client-removed')
+ .hook(Hyprland, (box, clientAddress) => {
+ const client = Hyprland.getClient(clientAddress);
+ if (!client) return;
+ box.attribute.updateWorkspace(box, client.workspace.id);
+ }, 'client-added')
+ .hook(Hyprland.active.workspace, (box) => {
+ // Full update when going to new ws group
+ const previousGroup = box.attribute.workspaceGroup;
+ const currentGroup = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN);
+ if (currentGroup !== previousGroup) {
+ box.attribute.update(box);
+ box.attribute.workspaceGroup = currentGroup;
+ }
+ })
+ .hook(App, (box, name, visible) => { // Update on open
+ if (name == 'overview' && visible) box.attribute.update(box);
+ })
+ },
+ });
+
+ return Widget.Revealer({
+ revealChild: true,
+ transition: 'slide_down',
+ transitionDuration: userOptions.animations.durationLarge,
+ child: Widget.Box({
+ vertical: true,
+ className: 'overview-tasks',
+ children: Array.from({ length: userOptions.overview.numOfRows }, (_, index) =>
+ OverviewRow({
+ startWorkspace: 1 + index * userOptions.overview.numOfCols,
+ workspaces: userOptions.overview.numOfCols,
+ })
+ )
+ }),
+ });
+} \ No newline at end of file
diff --git a/config/ags/modules/overview/searchbuttons.js b/config/ags/modules/overview/searchbuttons.js
new file mode 100644
index 00000000..f5892f31
--- /dev/null
+++ b/config/ags/modules/overview/searchbuttons.js
@@ -0,0 +1,163 @@
+const { Gtk } = imports.gi;
+import App from 'resource:///com/github/Aylur/ags/app.js';
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+const { execAsync, exec } = Utils;
+import { searchItem } from './searchitem.js';
+import { execAndClose, couldBeMath, launchCustomCommand } from './miscfunctions.js';
+
+export const DirectoryButton = ({ parentPath, name, type, icon }) => {
+ const actionText = Widget.Revealer({
+ revealChild: false,
+ transition: "crossfade",
+ transitionDuration: userOptions.animations.durationLarge,
+ child: Widget.Label({
+ className: 'overview-search-results-txt txt txt-small txt-action',
+ label: 'Open',
+ })
+ });
+ const actionTextRevealer = Widget.Revealer({
+ revealChild: false,
+ transition: "slide_left",
+ transitionDuration: userOptions.animations.durationSmall,
+ child: actionText,
+ });
+ return Widget.Button({
+ className: 'overview-search-result-btn',
+ onClicked: () => {
+ App.closeWindow('overview');
+ execAsync(['bash', '-c', `xdg-open '${parentPath}/${name}'`, `&`]).catch(print);
+ },
+ child: Widget.Box({
+ children: [
+ Widget.Box({
+ vertical: false,
+ children: [
+ Widget.Box({
+ className: 'overview-search-results-icon',
+ homogeneous: true,
+ child: Widget.Icon({
+ icon: icon,
+ }),
+ }),
+ Widget.Label({
+ className: 'overview-search-results-txt txt txt-norm',
+ label: name,
+ }),
+ Widget.Box({ hexpand: true }),
+ actionTextRevealer,
+ ]
+ })
+ ]
+ }),
+ setup: (self) => self
+ .on('focus-in-event', (button) => {
+ actionText.revealChild = true;
+ actionTextRevealer.revealChild = true;
+ })
+ .on('focus-out-event', (button) => {
+ actionText.revealChild = false;
+ actionTextRevealer.revealChild = false;
+ })
+ ,
+ })
+}
+
+export const CalculationResultButton = ({ result, text }) => searchItem({
+ materialIconName: '󱖦 ',
+ name: `Math result`,
+ actionName: "Copy",
+ content: `${result}`,
+ onActivate: () => {
+ App.closeWindow('overview');
+ execAsync(['wl-copy', `${result}`]).catch(print);
+ },
+});
+
+export const DesktopEntryButton = (app) => {
+ const actionText = Widget.Revealer({
+ revealChild: false,
+ transition: "crossfade",
+ transitionDuration: userOptions.animations.durationLarge,
+ child: Widget.Label({
+ className: 'overview-search-results-txt txt txt-small txt-action',
+ label: 'Launch',
+ })
+ });
+ const actionTextRevealer = Widget.Revealer({
+ revealChild: false,
+ transition: "slide_left",
+ transitionDuration: userOptions.animations.durationSmall,
+ child: actionText,
+ });
+ return Widget.Button({
+ className: 'overview-search-result-btn',
+ onClicked: () => {
+ App.closeWindow('overview');
+ app.launch();
+ },
+ child: Widget.Box({
+ children: [
+ Widget.Box({
+ vertical: false,
+ children: [
+ Widget.Box({
+ className: 'overview-search-results-icon',
+ homogeneous: true,
+ child: Widget.Icon({
+ icon: app.iconName,
+ }),
+ }),
+ Widget.Label({
+ className: 'overview-search-results-txt txt txt-norm',
+ label: app.name,
+ }),
+ Widget.Box({ hexpand: true }),
+ actionTextRevealer,
+ ]
+ })
+ ]
+ }),
+ setup: (self) => self
+ .on('focus-in-event', (button) => {
+ actionText.revealChild = true;
+ actionTextRevealer.revealChild = true;
+ })
+ .on('focus-out-event', (button) => {
+ actionText.revealChild = false;
+ actionTextRevealer.revealChild = false;
+ })
+ ,
+ })
+}
+
+export const ExecuteCommandButton = ({ command, terminal = false }) => searchItem({
+ materialIconName: `${terminal ? 'terminal' : ' '}`,
+ name: `Run command`,
+ actionName: `Execute ${terminal ? 'in terminal' : ''}`,
+ content: `${command}`,
+ onActivate: () => execAndClose(command, terminal),
+ extraClassName: 'techfont',
+})
+
+export const CustomCommandButton = ({ text = '' }) => searchItem({
+ materialIconName: ' ',
+ name: 'Action',
+ actionName: 'Run',
+ content: `${text}`,
+ onActivate: () => {
+ App.closeWindow('overview');
+ launchCustomCommand(text);
+ },
+});
+
+export const SearchButton = ({ text = '' }) => searchItem({
+ materialIconName: '󰜏 ',
+ name: 'Search the web',
+ actionName: 'Go',
+ content: `${text}`,
+ onActivate: () => {
+ App.closeWindow('overview');
+ execAsync(['bash', '-c', `xdg-open '${userOptions.search.engineBaseUrl}${text} ${['', ...userOptions.search.excludedSites].join(' -site:')}' &`]).catch(print);
+ },
+}); \ No newline at end of file
diff --git a/config/ags/modules/overview/searchitem.js b/config/ags/modules/overview/searchitem.js
new file mode 100644
index 00000000..2a3303a4
--- /dev/null
+++ b/config/ags/modules/overview/searchitem.js
@@ -0,0 +1,65 @@
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+
+export const searchItem = ({ materialIconName, name, actionName, content, onActivate, extraClassName = '', ...rest }) => {
+ const actionText = Widget.Revealer({
+ revealChild: false,
+ transition: "crossfade",
+ transitionDuration: userOptions.animations.durationLarge,
+ child: Widget.Label({
+ className: 'overview-search-results-txt txt txt-small txt-action',
+ label: `${actionName}`,
+ })
+ });
+ const actionTextRevealer = Widget.Revealer({
+ revealChild: false,
+ transition: "slide_left",
+ transitionDuration: userOptions.animations.durationSmall,
+ child: actionText,
+ })
+ return Widget.Button({
+ className: `overview-search-result-btn txt ${extraClassName}`,
+ onClicked: onActivate,
+ child: Widget.Box({
+ children: [
+ Widget.Box({
+ vertical: false,
+ children: [
+ Widget.Label({
+ className: `icon-material overview-search-results-icon`,
+ label: `${materialIconName}`,
+ }),
+ Widget.Box({
+ vertical: true,
+ children: [
+ Widget.Label({
+ hpack: 'start',
+ className: 'overview-search-results-txt txt-smallie txt-subtext',
+ label: `${name}`,
+ truncate: "end",
+ }),
+ Widget.Label({
+ hpack: 'start',
+ className: 'overview-search-results-txt txt-norm',
+ label: `${content}`,
+ truncate: "end",
+ }),
+ ]
+ }),
+ Widget.Box({ hexpand: true }),
+ actionTextRevealer,
+ ],
+ })
+ ]
+ }),
+ setup: (self) => self
+ .on('focus-in-event', (button) => {
+ actionText.revealChild = true;
+ actionTextRevealer.revealChild = true;
+ })
+ .on('focus-out-event', (button) => {
+ actionText.revealChild = false;
+ actionTextRevealer.revealChild = false;
+ })
+ ,
+ });
+}
diff --git a/config/ags/modules/overview/windowcontent.js b/config/ags/modules/overview/windowcontent.js
new file mode 100644
index 00000000..7a19dd3c
--- /dev/null
+++ b/config/ags/modules/overview/windowcontent.js
@@ -0,0 +1,262 @@
+const { Gdk, Gtk } = imports.gi;
+import App from 'resource:///com/github/Aylur/ags/app.js';
+import Widget from 'resource:///com/github/Aylur/ags/widget.js';
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+
+import Applications from 'resource:///com/github/Aylur/ags/service/applications.js';
+const { execAsync, exec } = Utils;
+import { execAndClose, expandTilde, hasUnterminatedBackslash, couldBeMath, launchCustomCommand, ls } from './miscfunctions.js';
+import {
+ CalculationResultButton, CustomCommandButton, DirectoryButton,
+ DesktopEntryButton, ExecuteCommandButton, SearchButton
+} from './searchbuttons.js';
+import { checkKeybind } from '../.widgetutils/keybind.js';
+
+// Add math funcs
+const { abs, sin, cos, tan, cot, asin, acos, atan, acot } = Math;
+const pi = Math.PI;
+// trigonometric funcs for deg
+const sind = x => sin(x * pi / 180);
+const cosd = x => cos(x * pi / 180);
+const tand = x => tan(x * pi / 180);
+const cotd = x => cot(x * pi / 180);
+const asind = x => asin(x) * 180 / pi;
+const acosd = x => acos(x) * 180 / pi;
+const atand = x => atan(x) * 180 / pi;
+const acotd = x => acot(x) * 180 / pi;
+
+const MAX_RESULTS = 10;
+const OVERVIEW_SCALE = 0.18; // = overview workspace box / screen size
+const OVERVIEW_WS_NUM_SCALE = 0.0;
+const OVERVIEW_WS_NUM_MARGIN_SCALE = 0.07;
+const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)];
+
+function iconExists(iconName) {
+ let iconTheme = Gtk.IconTheme.get_default();
+ return iconTheme.has_icon(iconName);
+}
+
+const OptionalOverview = async () => {
+ try {
+ return (await import('./overview_hyprland.js')).default();
+ } catch {
+ return Widget.Box({});
+ // return (await import('./overview_hyprland.js')).default();
+ }
+};
+
+const overviewContent = await OptionalOverview();
+
+export const SearchAndWindows = () => {
+ var _appSearchResults = [];
+
+ const ClickToClose = ({ ...props }) => Widget.EventBox({
+ ...props,
+ onPrimaryClick: () => App.closeWindow('overview'),
+ onSecondaryClick: () => App.closeWindow('overview'),
+ onMiddleClick: () => App.closeWindow('overview'),
+ });
+ const resultsBox = Widget.Box({
+ className: 'overview-search-results',
+ vertical: true,
+ vexpand: true,
+ });
+ const resultsRevealer = Widget.Revealer({
+ transitionDuration: userOptions.animations.durationLarge,
+ revealChild: false,
+ transition: 'slide_down',
+ // duration: 200,
+ hpack: 'center',
+ child: resultsBox,
+ });
+ const entryPromptRevealer = Widget.Revealer({
+ transition: 'crossfade',
+ transitionDuration: userOptions.animations.durationLarge,
+ revealChild: true,
+ hpack: 'center',
+ child: Widget.Label({
+ className: 'overview-search-prompt txt-small txt',
+ label: 'Type to search'
+ }),
+ });
+
+ const entryIconRevealer = Widget.Revealer({
+ transition: 'crossfade',
+ transitionDuration: userOptions.animations.durationLarge,
+ revealChild: false,
+ hpack: 'end',
+ child: Widget.Label({
+ className: 'txt txt-large icon-material overview-search-icon',
+ label: ' ',
+ }),
+ });
+
+ const entryIcon = Widget.Box({
+ className: 'overview-search-prompt-box',
+ setup: box => box.pack_start(entryIconRevealer, true, true, 0),
+ });
+
+ const entry = Widget.Entry({
+ className: 'overview-search-box txt-small txt',
+ hpack: 'center',
+ onAccept: (self) => { // This is when you hit Enter
+ const text = self.text;
+ if (text.length == 0) return;
+ const isAction = text.startsWith('>');
+ const isDir = (['/', '~'].includes(entry.text[0]));
+
+ if (couldBeMath(text)) { // Eval on typing is dangerous, this is a workaround
+ try {
+ const fullResult = eval(text.replace(/\^/g, "**"));
+ // copy
+ execAsync(['wl-copy', `${fullResult}`]).catch(print);
+ App.closeWindow('overview');
+ return;
+ } catch (e) {
+ // console.log(e);
+ }
+ }
+ if (isDir) {
+ App.closeWindow('overview');
+ execAsync(['bash', '-c', `xdg-open "${expandTilde(text)}"`, `&`]).catch(print);
+ return;
+ }
+ if (_appSearchResults.length > 0) {
+ App.closeWindow('overview');
+ _appSearchResults[0].launch();
+ return;
+ }
+ else if (text[0] == '>') { // Custom commands
+ App.closeWindow('overview');
+ launchCustomCommand(text);
+ return;
+ }
+ // Fallback: Execute command
+ if (!isAction && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') {
+ if (text.startsWith('sudo'))
+ execAndClose(text, true);
+ else
+ execAndClose(text, false);
+ }
+
+ else {
+ App.closeWindow('overview');
+ execAsync(['bash', '-c', `xdg-open '${userOptions.search.engineBaseUrl}${text} ${['', ...userOptions.search.excludedSites].join(' -site:')}' &`]).catch(print);
+ }
+ },
+ onChange: (entry) => { // this is when you type
+ const isAction = entry.text[0] == '>';
+ const isDir = (['/', '~'].includes(entry.text[0]));
+ resultsBox.get_children().forEach(ch => ch.destroy());
+
+ // check empty if so then dont do stuff
+ if (entry.text == '') {
+ resultsRevealer.revealChild = false;
+ overviewContent.revealChild = true;
+ entryPromptRevealer.revealChild = true;
+ entryIconRevealer.revealChild = false;
+ entry.toggleClassName('overview-search-box-extended', false);
+ return;
+ }
+ const text = entry.text;
+ resultsRevealer.revealChild = true;
+ overviewContent.revealChild = false;
+ entryPromptRevealer.revealChild = false;
+ entryIconRevealer.revealChild = true;
+ entry.toggleClassName('overview-search-box-extended', true);
+ _appSearchResults = Applications.query(text);
+
+ // Calculate
+ if (couldBeMath(text)) { // Eval on typing is dangerous; this is a small workaround.
+ try {
+ const fullResult = eval(text.replace(/\^/g, "**"));
+ resultsBox.add(CalculationResultButton({ result: fullResult, text: text }));
+ } catch (e) {
+ // console.log(e);
+ }
+ }
+ if (isDir) {
+ var contents = [];
+ contents = ls({ path: text, silent: true });
+ contents.forEach((item) => {
+ resultsBox.add(DirectoryButton(item));
+ })
+ }
+ if (isAction) { // Eval on typing is dangerous, this is a workaround.
+ resultsBox.add(CustomCommandButton({ text: entry.text }));
+ }
+ // Add application entries
+ let appsToAdd = MAX_RESULTS;
+ _appSearchResults.forEach(app => {
+ if (appsToAdd == 0) return;
+ resultsBox.add(DesktopEntryButton(app));
+ appsToAdd--;
+ });
+
+ // Fallbacks
+ // if the first word is an actual command
+ if (!isAction && !hasUnterminatedBackslash(text) && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') {
+ resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') }));
+ }
+
+ // Add fallback: search
+ resultsBox.add(SearchButton({ text: entry.text }));
+ resultsBox.show_all();
+ },
+ });
+ return Widget.Box({
+ vertical: true,
+ children: [
+ ClickToClose({ // Top margin. Also works as a click-outside-to-close thing
+ child: Widget.Box({
+ className: 'bar-height',
+ })
+ }),
+ Widget.Box({
+ hpack: 'center',
+ children: [
+ entry,
+ Widget.Box({
+ className: 'overview-search-icon-box',
+ setup: (box) => {
+ box.pack_start(entryPromptRevealer, true, true, 0)
+ },
+ }),
+ entryIcon,
+ ]
+ }),
+ overviewContent,
+ resultsRevealer,
+ ],
+ setup: (self) => self
+ .hook(App, (_b, name, visible) => {
+ if (name == 'overview' && !visible) {
+ resultsBox.children = [];
+ entry.set_text('');
+ }
+ })
+ .on('key-press-event', (widget, event) => { // Typing
+ const keyval = event.get_keyval()[1];
+ const modstate = event.get_state()[1];
+ if (checkKeybind(event, userOptions.keybinds.overview.altMoveLeft))
+ entry.set_position(Math.max(entry.get_position() - 1, 0));
+ else if (checkKeybind(event, userOptions.keybinds.overview.altMoveRight))
+ entry.set_position(Math.min(entry.get_position() + 1, entry.get_text().length));
+ else if (checkKeybind(event, userOptions.keybinds.overview.deleteToEnd)) {
+ const text = entry.get_text();
+ const pos = entry.get_position();
+ const newText = text.slice(0, pos);
+ entry.set_text(newText);
+ entry.set_position(newText.length);
+ }
+ else if (!(modstate & Gdk.ModifierType.CONTROL_MASK)) { // Ctrl not held
+ if (keyval >= 32 && keyval <= 126 && widget != entry) {
+ Utils.timeout(1, () => entry.grab_focus());
+ entry.set_text(entry.text + String.fromCharCode(keyval));
+ entry.set_position(-1);
+ }
+ }
+ })
+ ,
+ });
+};
diff --git a/config/ags/user/style.css b/config/ags/user/style.css
new file mode 100644
index 00000000..0519fb17
--- /dev/null
+++ b/config/ags/user/style.css
@@ -0,0 +1,198 @@
+*:not(popover) {
+ all: unset;
+}
+
+@import '../../../.cache/wal/colors-waybar.css';
+/* @import '../../../.cache/wal/colors-waybar-rgba.css'; */
+
+/* define some colors */
+@define-color border-color @color2;
+@define-color border-color-alt @color7;
+@define-color text-color rgba(255, 255, 255, 0.7);
+@define-color noti-bg rgba(0, 0, 0, 0.4);
+@define-color noti-bg-alt #111111;
+
+widget {
+ border-radius: 0.818rem;
+ -gtk-outline-radius: 0.818rem;
+}
+
+.overview-window {
+ margin-top: 2.727rem;
+}
+
+.overview-search-box {
+ transition: 300ms cubic-bezier(0, 0.55, 0.45, 1);
+ border-radius: 1.705rem;
+ -gtk-outline-radius: 1.705rem;
+ border-top: 1px solid @border-color;
+ border-left: 1px solid @border-color-alt;
+ border-right: 1px solid @border-color-alt;
+ border-bottom: 1px solid @border-color;
+ /* box-shadow: 0px 2px 3px alpha(@color0, 0.45); */
+ margin: 0.476rem;
+ min-width: 13.636rem;
+ min-height: 3.409rem;
+ padding: 0rem 1.364rem;
+ padding-right: 2.864rem;
+ background-color: @noti-bg;
+ color: @text-color;
+ caret-color: inherit;
+ font-weight: bolder;
+}
+.overview-search-box selection {
+ background-color: @noti-bg;
+ color: @text-color;
+}
+
+.overview-search-box-extended {
+ min-width: 25.909rem;
+ caret-color: #FDD9FD;
+}
+
+.overview-search-prompt {
+ color: @text-color;
+}
+
+.overview-search-icon {
+ margin: 0rem 1.023rem;
+}
+
+.overview-search-prompt-box {
+ margin-left: -18.545rem;
+ margin-right: 0.544rem;
+}
+
+.overview-search-icon-box {
+ margin-left: -18.545rem;
+ margin-right: 0.544rem;
+}
+
+.overview-search-results {
+ border-radius: 1.705rem;
+ -gtk-outline-radius: 1.705rem;
+ border-top: 1px solid @border-color;
+ border-left: 1px solid @border-color-alt;
+ border-right: 1px solid @border-color-alt;
+ border-bottom: 1px solid @border-color;
+ box-shadow: 0px 2px 3px @color9;
+ margin: 0.476rem;
+ min-width: 28.773rem;
+ padding: 0.682rem;
+ background-color: @noti-bg;
+ color: @text-color;
+ font-weight: bold;
+}
+
+.overview-search-results-icon {
+ margin: 0rem 0.682rem;
+ font-size: 2.386rem;
+ min-width: 2.386rem;
+ min-height: 2.386rem;
+}
+
+.overview-search-results-txt {
+ margin-right: 0.682rem;
+}
+
+.overview-search-results-txt-cmd {
+ margin-right: 0.682rem;
+ font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace;
+ font-size: 1.227rem;
+}
+
+.overview-search-result-btn {
+ border-radius: 1.159rem;
+ -gtk-outline-radius: 1.159rem;
+ padding: 0.341rem;
+ min-width: 2.386rem;
+ min-height: 2.386rem;
+ caret-color: transparent;
+}
+
+.overview-search-result-btn:hover,
+.overview-search-result-btn:focus {
+ background-color: alpha(@color7, 0.9);
+ color: alpha(@color0, 0.7);
+}
+
+.overview-search-result-btn:active {
+ background-color: alpha(@color7, 0.9);
+ color: @color4;
+}
+
+.overview-tasks {
+ border-radius: 1.705rem;
+ -gtk-outline-radius: 1.705rem;
+ border-top: 1px solid @border-color;
+ border-left: 1px solid @border-color-alt;
+ border-right: 1px solid @border-color-alt;
+ border-bottom: 1px solid @border-color;
+ box-shadow: 0px 2px 3px @color5;
+ margin: 0.476rem;
+ padding: 0.341rem;
+ /* background-color: rgba(49, 50, 68, 0.8); */
+ background-color: @noti-bg;
+ color: #EBDFED;
+}
+
+.overview-tasks-workspace {
+ border-radius: 1.159rem;
+ -gtk-outline-radius: 1.159rem;
+ margin: 0.341rem;
+ /* background-color: #26233A; */
+ background-image: url('../../rofi/.current_wallpaper');
+ background-size: cover;
+ background-position: center;
+ border: 0.068rem solid alpha(@color4, 0.5);
+}
+
+.overview-tasks-workspace-number {
+ font-family: "Open Sans", "Noto Sans", sans-serif;
+ color: #CFC2D3;
+}
+
+.overview-tasks-window {
+ border-radius: 1.159rem;
+ -gtk-outline-radius: 1.159rem;
+ transition: 300ms cubic-bezier(0.1, 1, 0, 1);
+ background-color: alpha(@color3, .7);
+ /* background-color: @color_a3; */
+ /* background-color: rgba(46, 40, 50, 0.8); */
+ color: #EBDFED;
+ border: 0.068rem solid @color7;
+}
+
+.overview-tasks-window:hover,
+.overview-tasks-window:focus {
+ background-color: alpha(@color9, 0.8);
+}
+
+.overview-tasks-window:active {
+ background-color: alpha(@color9, 0.8);
+}
+
+.overview-tasks-window-selected {
+ background-color: alpha(@color9, 0.8);
+}
+
+.overview-tasks-window-dragging {
+ opacity: 0.2;
+}
+
+.growingRadial {
+ transition: 300ms cubic-bezier(0.2, 0, 0, 1);
+}
+
+.fadingRadial {
+ transition: 50ms cubic-bezier(0.2, 0, 0, 1);
+}
+
+.sidebar-pinned {
+ margin: 0rem;
+ border-radius: 0rem;
+ border-bottom-right-radius: 1.705rem;
+ border: 0rem solid;
+}
+
+/*# sourceMappingURL=style.css.map */
diff --git a/config/ags/user_options.js b/config/ags/user_options.js
new file mode 100644
index 00000000..9105decb
--- /dev/null
+++ b/config/ags/user_options.js
@@ -0,0 +1,21 @@
+
+const userConfigOptions = {
+ // For every option, see ~/.config/ags/modules/.configuration/user_options.js
+ // (vscode users ctrl+click this: file://./modules/.configuration/user_options.js)
+ // (vim users: `:vsp` to split window, move cursor to this path, press `gf`. `Ctrl-w` twice to switch between)
+ // options listed in this file will override the default ones in the above file
+ // Here's an example
+ 'overview':{
+ 'scale': 0.15,
+ 'numOfRows': 2
+ },
+ 'keybinds': {
+ 'sidebar': {
+ 'pin': "Ctrl+p",
+ 'nextTab': "Ctrl+Page_Down",
+ 'prevTab': "Ctrl+Page_Up",
+ },
+ },
+}
+
+export default userConfigOptions;
diff --git a/config/ags/variables.js b/config/ags/variables.js
new file mode 100644
index 00000000..ec4aedec
--- /dev/null
+++ b/config/ags/variables.js
@@ -0,0 +1,21 @@
+const { Gtk } = imports.gi;
+import Variable from 'resource:///com/github/Aylur/ags/variable.js';
+import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
+const { exec, execAsync } = Utils;
+
+Gtk.IconTheme.get_default().append_search_path(`${App.configDir}/assets/icons`);
+
+// Screen size
+export const SCREEN_WIDTH = Number(exec(`bash -c "xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f1 | head -1" | awk '{print $1}'`));
+export const SCREEN_HEIGHT = Number(exec(`bash -c "xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f2 | head -1" | awk '{print $1}'`));
+
+// Mode switching
+export const currentShellMode = Variable('normal', {}) // normal, focus
+globalThis['currentMode'] = currentShellMode;
+globalThis['cycleMode'] = () => {
+ if (currentShellMode.value === 'normal') {
+ currentShellMode.value = 'focus';
+ } else {
+ currentShellMode.value = 'normal';
+ }
+}
diff --git a/config/hypr/UserConfigs/Startup_Apps.conf b/config/hypr/UserConfigs/Startup_Apps.conf
index 78d06363..2f529d61 100644
--- a/config/hypr/UserConfigs/Startup_Apps.conf
+++ b/config/hypr/UserConfigs/Startup_Apps.conf
@@ -23,6 +23,7 @@ exec-once = $scriptsDir/Polkit.sh
exec-once = waybar &
exec-once = nm-applet --indicator &
exec-once = swaync &
+exec-once = ags &
#exec-once = blueman-applet &
#exec-once = rog-control-center &
diff --git a/config/hypr/UserConfigs/UserKeybinds.conf b/config/hypr/UserConfigs/UserKeybinds.conf
index 7ffd702e..eede1669 100644
--- a/config/hypr/UserConfigs/UserKeybinds.conf
+++ b/config/hypr/UserConfigs/UserKeybinds.conf
@@ -15,6 +15,9 @@ $UserScripts = $HOME/.config/hypr/UserScripts
#bindr = $mainMod, $mainMod_L, exec, pkill rofi || rofi -show drun -modi drun,filebrowser,run,window # Super Key to Launch rofi menu
bind = $mainMod, D, exec, pkill rofi || rofi -show drun -modi drun,filebrowser,run,window
+# ags overview
+bind = $mainMod, A, exec, pkill rofi || true && ags -t 'overview'
+
bind = $mainMod, Return, exec, $term # Launch terminal
bind = $mainMod, T, exec, $files
diff --git a/config/hypr/UserConfigs/WindowRules.conf b/config/hypr/UserConfigs/WindowRules.conf
index 1cf23665..c07094bf 100644
--- a/config/hypr/UserConfigs/WindowRules.conf
+++ b/config/hypr/UserConfigs/WindowRules.conf
@@ -1,6 +1,7 @@
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
+#windowrule
windowrule = float, org.kde.polkit-kde-authentication-agent-1
windowrule = float, nm-connection-editor|blueman-manager
windowrule = float, pavucontrol
@@ -9,24 +10,25 @@ windowrule = float, onedriver|onedriver-launcher
windowrule = float, eog
windowrule = float, zoom
windowrule = float, rofi
-windowrule = float, gnome-system-monitor
+windowrule = float, ^(gnome-system-monitor|org.gnome.SystemMonitor)$
windowrule = float, yad
windowrule = float, ^(wihotspot-gui)$ # wifi hotspot
windowrule = float, ^(evince)$ # document viewer
-windowrule = float, ^(file-roller)$ # archive manager
+windowrule = float, ^(file-roller|org.gnome.FileRoller)$ # archive manager
#windowrule = noblur,gamescope
#windowrule = fullscreen,gamescope
#windowrule = workspace 6 silent,^(gamescope)$
windowrule = center,^(pavucontrol)
+windowrule = float, org.gnome.SystemMonitor
-# windowrule v2
+# windowrule v2 move to workspace
windowrulev2 = workspace 1, class:^([Tt]hunderbird)$
windowrulev2 = workspace 2, class:^([Ff]irefox)$
windowrulev2 = workspace 2, class:^(org.mozilla.firefox)$
windowrulev2 = workspace 2, class:^([Ff]irefox-esr)$
-windowrulev2 = workspace 2, class:^(Microsoft-edge-beta)$
-windowrulev2 = workspace 3, class:^([Tt]hunar)$
+windowrulev2 = workspace 2, class:^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable)?)$
+#windowrulev2 = workspace 3, class:^([Tt]hunar)$
windowrulev2 = workspace 4, class:^(com.obsproject.Studio)$
windowrulev2 = workspace 5 silent, class:^([Ss]team)$,title:^([Ss]team)$
windowrulev2 = workspace 5 silent, class:^(lutris)$
@@ -40,24 +42,16 @@ windowrulev2 = float, class:([Tt]hunar), title:(File Operation Progress)
windowrulev2 = float, class:([Tt]hunar), title:(Confirm to replace files)
windowrulev2 = float, class:(xdg-desktop-portal-gtk)
windowrulev2 = float, class:(org.gnome.Calculator), title:(Calculator)
-windowrulev2 = float, class:(codium), title:(Add Folder to Workspace)
-windowrulev2 = float, class:(codium-url-handler), title:(Add Folder to Workspace)
-windowrulev2 = float, class:(VSCodium), title:(Add Folder to Workspace)
+windowrulev2 = float, class:(codium|codium-url-handler|VSCodium), title:(Add Folder to Workspace)
-#opacity (transparent) #enable as desired
+# windowrule v2 - opacity #enable as desired
windowrulev2 = opacity 0.9 0.6, class:^([Rr]ofi)$
-windowrulev2 = opacity 0.9 0.7, class:^(Brave-browser)$
-windowrulev2 = opacity 0.9 0.7, class:^(Brave-browser-dev)$
+windowrulev2 = opacity 0.9 0.7, class:^(Brave-browser(-beta|-dev)?)$
windowrulev2 = opacity 0.9 0.7, class:^([Ff]irefox)$
windowrulev2 = opacity 0.9 0.7, class:^(org.mozilla.firefox)$
windowrulev2 = opacity 0.9 0.7, class:^([Ff]irefox-esr)$
-windowrulev2 = opacity 0.9 0.7, class:^([Mm]icrosoft-edge-stable)$
-windowrulev2 = opacity 0.9 0.7, class:^([Mm]icrosoft-edge-beta)$
-windowrulev2 = opacity 0.9 0.7, class:^([Mm]icrosoft-edge-dev)$
-windowrulev2 = opacity 0.9 0.8, class:^(google-chrome)$
-windowrulev2 = opacity 0.9 0.8, class:^(google-chrome-beta)$
-windowrulev2 = opacity 0.9 0.8, class:^(google-chrome-dev)$
-windowrulev2 = opacity 0.9 0.8, class:^(google-chrome-unstable)$
+windowrulev2 = opacity 0.9 0.8, class:^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable)?)$
+windowrulev2 = opacity 0.9 0.8, class:^(google-chrome(-beta|-dev|-unstable)?)$
windowrulev2 = opacity 0.94 0.86, class:^(chrome-.+-Default)$ # Chrome PWAs
windowrulev2 = opacity 0.9 0.8, class:^([Tt]hunar)$
windowrulev2 = opacity 0.8 0.6, class:^(pcmanfm-qt)$
@@ -66,21 +60,26 @@ windowrulev2 = opacity 0.9 0.8, class:^(deluge)$
windowrulev2 = opacity 0.9 0.8, class:^(Alacritty)$
windowrulev2 = opacity 0.9 0.8, class:^(kitty)$
windowrulev2 = opacity 0.9 0.7, class:^(mousepad)$
-windowrulev2 = opacity 0.9 0.7, class:^(codium-url-handler)$
-windowrulev2 = opacity 0.9 0.7, class:^(VSCodium)$
+windowrulev2 = opacity 0.9 0.7, class:^(VSCodium|codium-url-handler)$
windowrulev2 = opacity 0.9 0.7, class:^(yad)$
windowrulev2 = opacity 0.9 0.7, class:^(com.obsproject.Studio)$
windowrulev2 = opacity 0.9 0.7, class:^([Aa]udacious)$
windowrulev2 = opacity 0.9 0.8, class:^(org.gnome.Nautilus)$
-windowrulev2 = opacity 0.9 0.8, class:^(code-url-handler)$
-windowrulev2 = opacity 0.9 0.8, class:^(VSCode)$
+windowrulev2 = opacity 0.9 0.8, class:^(VSCode|code-url-handler)$
windowrulev2 = opacity 0.9 0.8, class:^(jetbrains-studio)$ # Android Studio
windowrulev2 = opacity 0.94 0.86, class:^(discord)$
windowrulev2 = opacity 0.9 0.8, class:^(org.telegram.desktop)$
windowrulev2 = opacity 0.94 0.86, class:^(gnome-disks)$
windowrulev2 = opacity 0.9 0.8, class:^(org.gnome.baobab)$
windowrulev2 = opacity 0.9 0.8, class:^(seahorse)$ # gnome-keyring gui
+windowrulev2 = opacity 0.82 0.75, class:^(gnome-system-monitor|org.gnome.SystemMonitor)$
+windowrulev2 = opacity 0.9 0.8, class:^(xdg-desktop-portal-gtk)$ # gnome-keyring gui
+# windowrule v2 - size
+windowrulev2 = size 70% 70%, class:^(gnome-system-monitor|org.gnome.SystemMonitor)$
+windowrulev2 = size 70% 70%, class:^(xdg-desktop-portal-gtk)$
+windowrulev2 = size 70% 70%, class:^(evince)$
+windowrulev2 = size 60% 70%, class:^(file-roller|org.gnome.FileRoller)$
#layerrule = unset,class:^([Rr]ofi)$
#layerrule = blur,class:^([Rr]ofi)$
diff --git a/config/hypr/UserScripts/Weather.py b/config/hypr/UserScripts/Weather.py
index 14c9cfe0..046dbcd3 100755
--- a/config/hypr/UserScripts/Weather.py
+++ b/config/hypr/UserScripts/Weather.py
@@ -3,7 +3,7 @@
import subprocess
from pyquery import PyQuery # install using `pip install pyquery`
import json
-
+import os
# original code https://gist.github.com/Surendrajat/ff3876fd2166dd86fb71180f4e9342d7
# weather icons
@@ -122,3 +122,15 @@ out_data = {
"class": status_code,
}
print(json.dumps(out_data))
+
+simple_weather =f"{icon} {status}\n" + \
+ f" {temp} ({temp_feel_text})\n" + \
+ f"{wind_text}\n" + \
+ f"{humidity_text}\n" + \
+ f"{visbility_text} AQI {air_quality_index}\n"
+
+try:
+ with open(os.path.expanduser("~/.cache/.weather_cache"), "w") as file:
+ file.write(simple_weather)
+except:
+ pass \ No newline at end of file
diff --git a/config/hypr/UserScripts/Weather.sh b/config/hypr/UserScripts/Weather.sh
index 40048710..f916b028 100755
--- a/config/hypr/UserScripts/Weather.sh
+++ b/config/hypr/UserScripts/Weather.sh
@@ -78,3 +78,7 @@ esac
#echo $temp $condition
echo -e "{\"text\":\""$temperature $condition"\", \"alt\":\""${weather[0]}"\", \"tooltip\":\""${weather[0]}: $temperature ${weather[1]}"\"}"
+
+cached_weather=" $temperature \n$condition ${weather[1]}"
+
+echo -e $cached_weather > ~/.cache/.weather_cache \ No newline at end of file
diff --git a/config/hypr/configs/Keybinds.conf b/config/hypr/configs/Keybinds.conf
index 1cc8e2af..2cdd9cde 100644
--- a/config/hypr/configs/Keybinds.conf
+++ b/config/hypr/configs/Keybinds.conf
@@ -30,7 +30,6 @@ bind = $mainMod ALT, L, exec, $scriptsDir/ChangeLayout.sh # Toggle Master or Dwi
bind = $mainMod ALT, V, exec, $scriptsDir/ClipManager.sh # Clipboard Manager
bind = $mainMod SHIFT, N, exec, swaync-client -t -sw # swayNC panel
bind = SHIFT, ALT_L, exec, $scriptsDir/SwitchKeyboardLayout.sh # Switch Keyboard Layout
-bind = $mainMod, A, exec, ags -t 'overview'
# FEATURES / EXTRAS (UserScripts)
bind = $mainMod, E, exec, $UserScripts/QuickEdit.sh # Quick Edit Hyprland Settings
@@ -77,7 +76,7 @@ bind = $mainMod, Print, exec, $scriptsDir/ScreenShot.sh --now
bind = $mainMod SHIFT, Print, exec, $scriptsDir/ScreenShot.sh --area
bind = $mainMod CTRL, Print, exec, $scriptsDir/ScreenShot.sh --in5 #screenshot in 5 secs
bind = $mainMod ALT, Print, exec, $scriptsDir/ScreenShot.sh --in10 #screenshot in 10 secs
-bind = ALT, Print, exec, $scriptsDir/ScreenShot.sh --active #screenshot in 10 secs
+bind = ALT, Print, exec, $scriptsDir/ScreenShot.sh --active #take screenshot of active window
# screenshot with swappy (another screenshot tool)
bind = $mainMod SHIFT, S, exec, $scriptsDir/ScreenShot.sh --swappy
diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf
index 3aa029d9..38c927a0 100644
--- a/config/hypr/hyprlock.conf
+++ b/config/hypr/hyprlock.conf
@@ -110,7 +110,7 @@ label {
# weather edit specific location. Note, this cause a 2-4 seconds delay in locking
label {
monitor =
- text = cmd[update:3600000] ping -c 1 wttr.in > /dev/null && curl -s 'wttr.in?format=2' # For specific location : wttr.in/busan?format=2
+ text = cmd[update:3600000] [ -f ~/.cache/.weather_cache ] && cat ~/.cache/.weather_cache
color = $color10
font_size = 24
font_family = JetBrains Mono Nerd Font 10
diff --git a/config/hypr/scripts/DarkLight.sh b/config/hypr/scripts/DarkLight.sh
index 6c9f610f..f9d2a933 100755
--- a/config/hypr/scripts/DarkLight.sh
+++ b/config/hypr/scripts/DarkLight.sh
@@ -9,6 +9,7 @@ dark_wallpapers="$wallpaper_base_path/Dark"
light_wallpapers="$wallpaper_base_path/Light"
hypr_config_path="$HOME/.config/hypr"
swaync_style="$HOME/.config/swaync/style.css"
+ags_style="$HOME/.config/ags/user/style.css"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
notif="$HOME/.config/swaync/images/bell.png"
dark_rofi_pywal="$HOME/.cache/wal/colors-rofi-dark.rasi"
@@ -74,6 +75,17 @@ else
sed -i '/@define-color noti-bg-alt/s/#.*;/#F0F0F0;/' "${swaync_style}"
fi
+# ags color change
+if [ "$next_mode" = "Dark" ]; then
+ sed -i '/@define-color noti-bg/s/rgba([0-9]*,\s*[0-9]*,\s*[0-9]*,\s*[0-9.]*);/rgba(0, 0, 0, 0.4);/' "${ags_style}"
+ sed -i '/@define-color text-color/s/rgba([0-9]*,\s*[0-9]*,\s*[0-9]*,\s*[0-9.]*);/rgba(255, 255, 255, 0.7);/' "${ags_style}"
+ sed -i '/@define-color noti-bg-alt/s/#.*;/#111111;/' "${ags_style}"
+else
+ sed -i '/@define-color noti-bg/s/rgba([0-9]*,\s*[0-9]*,\s*[0-9]*,\s*[0-9.]*);/rgba(255, 255, 255, 0.4);/' "${ags_style}"
+ sed -i '/@define-color text-color/s/rgba([0-9]*,\s*[0-9]*,\s*[0-9]*,\s*[0-9.]*);/rgba(0, 0, 0, 0.7);/' "${ags_style}"
+ sed -i '/@define-color noti-bg-alt/s/#.*;/#F0F0F0;/' "${ags_style}"
+fi
+
# Set Dynamic Wallpaper for Dark or Light Mode
if [ "$next_mode" = "Dark" ]; then
next_wallpaper="$(find "${dark_wallpapers}" -type f \( -iname "*.jpg" -o -iname "*.png" \) -print0 | shuf -n1 -z | xargs -0)"
diff --git a/config/hypr/scripts/Refresh.sh b/config/hypr/scripts/Refresh.sh
index bf806e01..aeae77d1 100755
--- a/config/hypr/scripts/Refresh.sh
+++ b/config/hypr/scripts/Refresh.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
-# Scripts for refreshing waybar, rofi, swaync, pywal colors
+# Scripts for refreshing ags waybar, rofi, swaync, pywal colors
SCRIPTSDIR=$HOME/.config/hypr/scripts
UserScripts=$HOME/.config/hypr/UserScripts
@@ -22,6 +22,7 @@ for _prs in "${_ps[@]}"; do
fi
done
+# quit ags
ags -q
sleep 0.3
diff --git a/config/hypr/scripts/RefreshNoWaybar.sh b/config/hypr/scripts/RefreshNoWaybar.sh
index 689bccf0..42d67adc 100755
--- a/config/hypr/scripts/RefreshNoWaybar.sh
+++ b/config/hypr/scripts/RefreshNoWaybar.sh
@@ -25,6 +25,9 @@ for _prs in "${_ps[@]}"; do
fi
done
+# quit ags
+ags -q
+
# Pywal refresh
${SCRIPTSDIR}/PywalSwww.sh &
diff --git a/config/hypr/scripts/Wlogout.sh b/config/hypr/scripts/Wlogout.sh
index 58e1fd68..f3746530 100755
--- a/config/hypr/scripts/Wlogout.sh
+++ b/config/hypr/scripts/Wlogout.sh
@@ -4,12 +4,14 @@
# wlogout (Power, Screen Lock, Suspend, etc)
# Set variables for parameters
-A_2160=680
-B_2160=750
-A_1440=500
-B_1440=550
-A_1080=400
-B_1080=400
+A_2160=450
+B_2160=450
+A_1600=400
+B_1600=400
+A_1440=350
+B_1440=350
+A_1080=50
+B_1080=50
A_720=50
B_720=50
@@ -23,22 +25,33 @@ fi
resolution=$(hyprctl -j monitors | jq -r '.[] | select(.focused==true) | .height / .scale' | awk -F'.' '{print $1}')
hypr_scale=$(hyprctl -j monitors | jq -r '.[] | select(.focused==true) | .scale')
-echo "Detected Resolution: $resolution"
-
# Set parameters based on screen resolution and scaling factor
if ((resolution >= 2160)); then
- wlogout --protocol layer-shell -b 3 -T $(awk "BEGIN {printf \"%.0f\", $A_2160 * 2160 * $hypr_scale / $resolution}") -B $(awk "BEGIN {printf \"%.0f\", $B_2160 * 2160 * $hypr_scale / $resolution}") &
- echo "Setting parameters for resolution >= 2160p"
-elif ((resolution >= 1440)); then
- wlogout --protocol layer-shell -b 6 -T $(awk "BEGIN {printf \"%.0f\", $A_1440 * 1440 * $hypr_scale / $resolution}") -B $(awk "BEGIN {printf \"%.0f\", $B_1440 * 1440 * $hypr_scale / $resolution}") &
- echo "Setting parameters for resolution >= 1440p"
-elif ((resolution >= 1080)); then
- wlogout --protocol layer-shell -b 6 -T $(awk "BEGIN {printf \"%.0f\", $A_1080 * 1080 * $hypr_scale / $resolution}") -B $(awk "BEGIN {printf \"%.0f\", $B_1080 * 1080 * $hypr_scale / $resolution}") &
- echo "Setting parameters for resolution >= 1080p"
-elif ((resolution > 720)); then
- wlogout --protocol layer-shell -b 3 -T $(awk "BEGIN {printf \"%.0f\", $A_720 * 720 * $hypr_scale / $resolution}") -B $(awk "BEGIN {printf \"%.0f\", $B_720 * 720 * $hypr_scale / $resolution}") &
- echo "Setting parameters for resolution >= 720p"
+ T_val=$(awk "BEGIN {printf \"%.0f\", $A_2160 * 2160 * $hypr_scale / $resolution}")
+ B_val=$(awk "BEGIN {printf \"%.0f\", $B_2160 * 2160 * $hypr_scale / $resolution}")
+ echo "Setting parameters for resolution >= 4k"
+ wlogout --protocol layer-shell -b 6 -T $T_val -B $B_val &
+elif ((resolution >= 1600 && resolution < 2160)); then
+ T_val=$(awk "BEGIN {printf \"%.0f\", $A_1600 * 1600 * $hypr_scale / $resolution}")
+ B_val=$(awk "BEGIN {printf \"%.0f\", $B_1600 * 1600 * $hypr_scale / $resolution}")
+ echo "Setting parameters for resolution >= 2.5k and < 4k"
+ wlogout --protocol layer-shell -b 6 -T $T_val -B $B_val &
+elif ((resolution >= 1440 && resolution < 1600)); then
+ T_val=$(awk "BEGIN {printf \"%.0f\", $A_1440 * 1440 * $hypr_scale / $resolution}")
+ B_val=$(awk "BEGIN {printf \"%.0f\", $B_1440 * 1440 * $hypr_scale / $resolution}")
+ echo "Setting parameters for resolution >= 2k and < 2.5k"
+ wlogout --protocol layer-shell -b 6 -T $T_val -B $B_val &
+elif ((resolution >= 1080 && resolution < 1440)); then
+ T_val=$(awk "BEGIN {printf \"%.0f\", $A_1080 * 1080 * $hypr_scale / $resolution}")
+ B_val=$(awk "BEGIN {printf \"%.0f\", $B_1080 * 1080 * $hypr_scale / $resolution}")
+ echo "Setting parameters for resolution >= 1080p and < 2k"
+ wlogout --protocol layer-shell -b 3 -T $T_val -B $B_val &
+elif ((resolution >= 720 && resolution < 1080)); then
+ T_val=$(awk "BEGIN {printf \"%.0f\", $A_720 * 720 * $hypr_scale / $resolution}")
+ B_val=$(awk "BEGIN {printf \"%.0f\", $B_720 * 720 * $hypr_scale / $resolution}")
+ echo "Setting parameters for resolution >= 720p and < 1080p"
+ wlogout --protocol layer-shell -b 3 -T $T_val -B $B_val &
else
+ echo "Setting default parameters"
wlogout &
- echo "Setting default parameters for resolution <= 720p"
-fi \ No newline at end of file
+fi
diff --git a/config/hypr/v2.2.10 b/config/hypr/v2.2.11
index 31b3414d..31b3414d 100644
--- a/config/hypr/v2.2.10
+++ b/config/hypr/v2.2.11
diff --git a/config/rofi/config-compact.rasi b/config/rofi/config-compact.rasi
index e35ec79d..2c72252e 100644
--- a/config/rofi/config-compact.rasi
+++ b/config/rofi/config-compact.rasi
@@ -10,32 +10,31 @@ configuration {
/* ---- Window ---- */
window {
- width: 24%;
+ width: 50%;
border-radius: 15px;
}
/* ---- Inputbar ---- */
inputbar {
- background-image: url("~/.config/rofi/.current_wallpaper", width);
+ background-image: url("~/.config/rofi/.current_wallpaper", width);
}
/* ---- Imagebox ---- */
imagebox {
orientation: vertical;
- children:
- [ "entry", "listview"];
+ children: [ "entry", "listview"];
}
/* ---- Entry input ---- */
entry {
- width: 18%;
+ width: 23%;
placeholder: " View / Edit Hyprland Configs";
}
/* ---- Listview ---- */
listview {
- columns: 1;
- lines: 10;
+ columns: 2;
+ lines: 5;
spacing: 4px;
scrollbar: false;
border-radius: 12px;
diff --git a/config/rofi/config-long.rasi b/config/rofi/config-long.rasi
index b75d3d5e..2341e5f6 100644
--- a/config/rofi/config-long.rasi
+++ b/config/rofi/config-long.rasi
@@ -5,7 +5,7 @@
/* ---- Window ---- */
window {
- width: 50%;
+ width: 50%;
}
/* ---- Entry ---- */
@@ -16,5 +16,6 @@ entry {
/* ---- Listview ---- */
listview {
columns: 1;
- lines: 10;
+ lines: 8;
+ scrollbar: true;
} \ No newline at end of file
diff --git a/config/rofi/config-rofi-Beats.rasi b/config/rofi/config-rofi-Beats.rasi
index efd67033..82de4a6c 100644
--- a/config/rofi/config-rofi-Beats.rasi
+++ b/config/rofi/config-rofi-Beats.rasi
@@ -10,5 +10,5 @@ entry {
/* ---- Listview ---- */
listview {
- lines: 10;
+ lines: 6;
} \ No newline at end of file
diff --git a/config/rofi/config-waybar-style.rasi b/config/rofi/config-waybar-style.rasi
index 55c61567..aebe6861 100644
--- a/config/rofi/config-waybar-style.rasi
+++ b/config/rofi/config-waybar-style.rasi
@@ -22,6 +22,7 @@ entry {
/* ---- Listview ---- */
listview {
columns: 2;
- lines: 8;
- scrollbar: false;
+ lines: 6;
+ scrollbar: true;
}
+
diff --git a/config/rofi/config.rasi b/config/rofi/config.rasi
index 5a161f29..2c8b9658 100755
--- a/config/rofi/config.rasi
+++ b/config/rofi/config.rasi
@@ -84,7 +84,7 @@ entry {
background-color: @background-alt;
text-color: inherit;
cursor: text;
- placeholder: " Search "; // << Search symbol
+ placeholder: "🔎 Search "; // << Search symbol
placeholder-color: inherit;
}
@@ -107,7 +107,7 @@ listview {
scrollbar: false;
layout: vertical;
reverse: false;
- fixed-height: true;
+ fixed-height: false;
fixed-columns: true;
spacing: 10px;
background-color: transparent;
@@ -141,6 +141,14 @@ button selected {
text-color: @text-selected;
}
+/* ---- Scrollbar ---- */
+scrollbar {
+ width: 4px ;
+ border: 0;
+ handle-color: @border-color;
+ handle-width: 8px ;
+ padding: 0;
+}
/* ---- Elements ---- */
element {
@@ -152,7 +160,6 @@ element {
cursor: pointer;
}
-
element normal.normal {
background-color: inherit;
text-color: inherit;
diff --git a/config/rofi/resolution/1080p/config.rasi b/config/rofi/resolution/1080p/config.rasi
index 5a161f29..2c8b9658 100755
--- a/config/rofi/resolution/1080p/config.rasi
+++ b/config/rofi/resolution/1080p/config.rasi
@@ -84,7 +84,7 @@ entry {
background-color: @background-alt;
text-color: inherit;
cursor: text;
- placeholder: " Search "; // << Search symbol
+ placeholder: "🔎 Search "; // << Search symbol
placeholder-color: inherit;
}
@@ -107,7 +107,7 @@ listview {
scrollbar: false;
layout: vertical;
reverse: false;
- fixed-height: true;
+ fixed-height: false;
fixed-columns: true;
spacing: 10px;
background-color: transparent;
@@ -141,6 +141,14 @@ button selected {
text-color: @text-selected;
}
+/* ---- Scrollbar ---- */
+scrollbar {
+ width: 4px ;
+ border: 0;
+ handle-color: @border-color;
+ handle-width: 8px ;
+ padding: 0;
+}
/* ---- Elements ---- */
element {
@@ -152,7 +160,6 @@ element {
cursor: pointer;
}
-
element normal.normal {
background-color: inherit;
text-color: inherit;
diff --git a/config/rofi/resolution/1440p/config.rasi b/config/rofi/resolution/1440p/config.rasi
index 1ed79730..ae3a7b7a 100644..100755
--- a/config/rofi/resolution/1440p/config.rasi
+++ b/config/rofi/resolution/1440p/config.rasi
@@ -84,7 +84,7 @@ entry {
background-color: @background-alt;
text-color: @text-selected;
cursor: text;
- placeholder: " Search "; // << Search symbol
+ placeholder: "🔎 Search "; // << Search symbol
placeholder-color: inherit;
}
@@ -107,7 +107,7 @@ listview {
scrollbar: false;
layout: vertical;
reverse: false;
- fixed-height: true;
+ fixed-height: false;
fixed-columns: true;
spacing: 10px;
background-color: transparent;
@@ -141,6 +141,14 @@ button selected {
text-color: @text-selected;
}
+/* ---- Scrollbar ---- */
+scrollbar {
+ width: 4px ;
+ border: 0;
+ handle-color: @border-color;
+ handle-width: 8px ;
+ padding: 0;
+}
/* ---- Elements ---- */
element {
@@ -152,7 +160,6 @@ element {
cursor: pointer;
}
-
element normal.normal {
background-color: inherit;
text-color: inherit;
diff --git a/config/waybar/modules b/config/waybar/modules
index f42f89d0..a2357e20 100644
--- a/config/waybar/modules
+++ b/config/waybar/modules
@@ -192,7 +192,7 @@
"critical": 15
},
"format": "{icon} {capacity}%",
- "format-charging": "{capacity}%",
+ "format-charging": " {capacity}%",
"format-plugged": "󱘖 {capacity}%",
"format-alt-click": "click",
"format-full": "{icon} Full",
diff --git a/config/waybar/style/Catppuccin-Latte.css b/config/waybar/style/[Catppuccin] Latte.css
index 3f344079..3f344079 100644
--- a/config/waybar/style/Catppuccin-Latte.css
+++ b/config/waybar/style/[Catppuccin] Latte.css
diff --git a/config/waybar/style/Catppuccin-Mocha.css b/config/waybar/style/[Catppuccin] Mocha.css
index 5ce97eac..5ce97eac 100644
--- a/config/waybar/style/Catppuccin-Mocha.css
+++ b/config/waybar/style/[Catppuccin] Mocha.css
diff --git a/config/waybar/style/[Colored] Translucent.css b/config/waybar/style/[Colored] Translucent.css
index 5998227a..37931d58 100644
--- a/config/waybar/style/[Colored] Translucent.css
+++ b/config/waybar/style/[Colored] Translucent.css
@@ -50,17 +50,13 @@ window#waybar.empty #window {
tooltip {
background: #1e1e2e;
- opacity: 0.8;
+ opacity: 0.6;
border-radius: 10px;
border-width: 2px;
border-style: solid;
border-color: #11111b;
}
-tooltip label{
- color: #cdd6f4;
-}
-
#workspaces button {
background-color: transparent;
color: #ffffff;
diff --git a/config/waybar/style/[Colorful] Aurora Blossom.css b/config/waybar/style/[Colorful] Aurora Blossom.css
index 9eab49ad..d785453c 100644
--- a/config/waybar/style/[Colorful] Aurora Blossom.css
+++ b/config/waybar/style/[Colorful] Aurora Blossom.css
@@ -32,6 +32,7 @@ tooltip {
tooltip label{
color: black;
}
+
/*-----module groups----*/
.modules-right {
background-image: linear-gradient(45deg, #7287fd 10%, #209fb5 54%, #8839ef 90%);
diff --git a/config/waybar/style/Purpl.css b/config/waybar/style/[Dark] Purpl.css
index 0e463834..0e463834 100644
--- a/config/waybar/style/Purpl.css
+++ b/config/waybar/style/[Dark] Purpl.css
diff --git a/config/waybar/style/Crimson.css b/config/waybar/style/[Extra] Crimson.css
index 89a3b9cf..c6530e11 100644
--- a/config/waybar/style/Crimson.css
+++ b/config/waybar/style/[Extra] Crimson.css
@@ -34,12 +34,12 @@ window#waybar.empty #window {
}
tooltip {
- background: #1e1e2e;
+ background: #240303;
border-radius: 10px;
border-width: 2px;
border-style: solid;
border-color: #11111b;
- color: #cba6f7;
+ color: wheat;
}
/*-----module groups----*/
diff --git a/config/waybar/style/Mauve.css b/config/waybar/style/[Extra] Mauve.css
index 685025fc..685025fc 100644
--- a/config/waybar/style/Mauve.css
+++ b/config/waybar/style/[Extra] Mauve.css
diff --git a/config/waybar/style/Rose Pine.css b/config/waybar/style/[Extra] Rose Pine.css
index 783ea1da..783ea1da 100644
--- a/config/waybar/style/Rose Pine.css
+++ b/config/waybar/style/[Extra] Rose Pine.css
diff --git a/config/waybar/style/Simple Pink.css b/config/waybar/style/[Extra] Simple Pink.css
index 2f41cbb4..2f41cbb4 100644
--- a/config/waybar/style/Simple Pink.css
+++ b/config/waybar/style/[Extra] Simple Pink.css
diff --git a/config/waybar/style/[Bordered Pywal] Chroma Fusion Edge.css b/config/waybar/style/[Pywal Bordered] Chroma Fusion Edge.css
index 04ca9248..89977952 100644
--- a/config/waybar/style/[Bordered Pywal] Chroma Fusion Edge.css
+++ b/config/waybar/style/[Pywal Bordered] Chroma Fusion Edge.css
@@ -47,6 +47,15 @@ window#waybar.empty #window {
}
+tooltip {
+ background-color: transparent;
+ border-radius: 10px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #11111b;
+ color: @border-color;
+}
+
#backlight,
#backlight-slider,
#battery,
diff --git a/config/waybar/style/[Pywal] Chroma Fusion.css b/config/waybar/style/[Pywal] Chroma Fusion.css
index 90e2e7a5..00e50ef6 100644
--- a/config/waybar/style/[Pywal] Chroma Fusion.css
+++ b/config/waybar/style/[Pywal] Chroma Fusion.css
@@ -46,6 +46,15 @@ window#waybar.empty #window {
}
+tooltip {
+ background-color: @background-module;
+ border-radius: 10px;
+ border-width: 2px;
+ border-style: solid;
+ border-color: #11111b;
+ color: @color2;
+}
+
#backlight,
#backlight-slider,
#battery,
diff --git a/config/waybar/style/[Pywal] Chroma Tally.css b/config/waybar/style/[Pywal] Chroma Tally.css
index 41a15f32..fe3bc0f1 100644
--- a/config/waybar/style/[Pywal] Chroma Tally.css
+++ b/config/waybar/style/[Pywal] Chroma Tally.css
@@ -62,6 +62,12 @@ window#waybar {
}
+tooltip {
+ background: #1e1e2e;
+ opacity: 0.8;
+ border-radius: 6px;
+}
+
#backlight,
#backlight-slider,
#battery,
diff --git a/config/waybar/style/[Transparent] Crystal Clear.css b/config/waybar/style/[Transparent] Crystal Clear.css
index 430072dd..0003efed 100644
--- a/config/waybar/style/[Transparent] Crystal Clear.css
+++ b/config/waybar/style/[Transparent] Crystal Clear.css
@@ -33,14 +33,6 @@ window#waybar.empty #window {
background-color: transparent;
}
-tooltip {
- background: #1e1e2e;
- border-radius: 10px;
- border-width: 2px;
- border-style: solid;
- border-color: #11111b;
- color: #cba6f7;
-}
/*-----module groups----*/
.modules-right {
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage