From 74f3f1ec2c98e08332cff8e141604a75ceaeacbc Mon Sep 17 00:00:00 2001 From: RubberJones <5031378+RubberJones@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:37:41 +0200 Subject: refactor(copy.sh): Remove duplicate print_color function --- copy.sh | 5 ----- 1 file changed, 5 deletions(-) (limited to 'copy.sh') diff --git a/copy.sh b/copy.sh index 0c556ddd..b405a777 100755 --- a/copy.sh +++ b/copy.sh @@ -75,11 +75,6 @@ if [ ! -d Copy-Logs ]; then mkdir Copy-Logs fi -# Function to print colorful text -print_color() { - printf "%b%s%b\n" "$1" "$2" "$CLEAR" -} - # Set the name of the log file to include the current date and time LOG="Copy-Logs/install-$(date +%d-%H%M%S)_dotfiles.log" -- cgit v1.2.3 From 9c4c63d3e0b49ba94e8166603717ae055a7d6f12 Mon Sep 17 00:00:00 2001 From: RubberJones <5031378+RubberJones@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:46:18 +0200 Subject: fix(copy.sh): Correct variable for resetting color in function Replace the undefined variable $CLEAR with the correct variable $RESET. The function attempted to reset the text color using the $CLEAR variable, which, however, was not defined anywhere in the script. This resulted in the color output not being reset after the function call. This change ensures that the correct, already defined $RESET variable is used to reset the terminal to its default state. --- copy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'copy.sh') diff --git a/copy.sh b/copy.sh index b405a777..88b42abf 100755 --- a/copy.sh +++ b/copy.sh @@ -33,7 +33,7 @@ fi # Function to print colorful text print_color() { - printf "%b%s%b\n" "$1" "$2" "$CLEAR" + printf "%b%s%b\n" "$1" "$2" "$RESET" } # Check /etc/os-release to see if this is an Ubuntu or Debian based distro -- cgit v1.2.3 From b37cf284a9d1ebd6583ba8489195c755c65935d8 Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Tue, 15 Jul 2025 19:33:34 +0900 Subject: Introducing QuickShell --- config/hypr/UserConfigs/UserSettings.conf | 2 -- config/hypr/scripts/Refresh.sh | 4 +-- config/hypr/scripts/RefreshNoWaybar.sh | 2 +- copy.sh | 51 ++++++++++++++++++++++++++----- 4 files changed, 47 insertions(+), 12 deletions(-) (limited to 'copy.sh') diff --git a/config/hypr/UserConfigs/UserSettings.conf b/config/hypr/UserConfigs/UserSettings.conf index 29dbc572..1f8c23c3 100644 --- a/config/hypr/UserConfigs/UserSettings.conf +++ b/config/hypr/UserConfigs/UserSettings.conf @@ -104,8 +104,6 @@ xwayland { } render { - #explicit_sync = 2 - #explicit_sync_kms = 2 direct_scanout = 0 } diff --git a/config/hypr/scripts/Refresh.sh b/config/hypr/scripts/Refresh.sh index 2d7887a5..d04570b1 100755 --- a/config/hypr/scripts/Refresh.sh +++ b/config/hypr/scripts/Refresh.sh @@ -25,8 +25,8 @@ done # added since wallust sometimes not applying killall -SIGUSR2 waybar -# quit ags & relaunch ags -#ags -q && ags & +# quit quickshell & relaunch quickshell +#pkill qs && qs & # some process to kill for pid in $(pidof waybar rofi swaync ags swaybg); do diff --git a/config/hypr/scripts/RefreshNoWaybar.sh b/config/hypr/scripts/RefreshNoWaybar.sh index e5a0835e..cdbb82db 100755 --- a/config/hypr/scripts/RefreshNoWaybar.sh +++ b/config/hypr/scripts/RefreshNoWaybar.sh @@ -26,7 +26,7 @@ for _prs in "${_ps[@]}"; do done # quit ags & relaunch ags -#ags -q && ags & +#pkill qs && qs & # Wallust refresh ${SCRIPTSDIR}/WallustSwww.sh & diff --git a/copy.sh b/copy.sh index 0c556ddd..f752ac92 100755 --- a/copy.sh +++ b/copy.sh @@ -240,11 +240,11 @@ if command -v blueman-applet >/dev/null 2>&1; then sed -i '/^\s*#exec-once = blueman-applet/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf fi -# Check if ags is installed edit ags behaviour on configs -if command -v ags >/dev/null 2>&1; then - sed -i '/^\s*#exec-once = ags/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf - sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh - sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/Refresh.sh +# Check if quickshell is installed edit quickshell behaviour on configs +if command -v qs >/dev/null 2>&1; then + sed -i '/^\s*#exec-once = qs/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf + sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh + sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/Refresh.sh fi printf "\n%.0s" {1..1} @@ -461,7 +461,7 @@ fi printf "${INFO} - copying dotfiles ${SKY_BLUE}first${RESET} part\n" # Config directories which will ask the user whether to replace or not -DIRS="ags fastfetch kitty rofi swaync" +DIRS="fastfetch kitty rofi swaync" for DIR2 in $DIRS; do DIRPATH="$HOME/.config/$DIR2" @@ -670,6 +670,43 @@ done printf "\n%.0s" {1..1} +# quickshell (ags alternative) +# Check if quickshell is running +if pgrep -x "qs" >/dev/null; then + echo -e "${NOTE} - ${YELLOW}quickshell${RESET} is currently installed and running." + + DIRPATH_QS="$HOME/.config/quickshell" + + if [ ! -d "$DIRPATH_QS" ]; then + echo "${INFO} - quickshell config not found, copying new config." + if [ -d "config/quickshell" ]; then + cp -r "config/quickshell/" "$DIRPATH" 2>&1 | tee -a "$LOG" + fi + else + read -p "${CAT} Do you want to overwrite your existing ${YELLOW}quickshell${RESET} config? [y/N] " answer_qs + case "$answer_qs" in + [Yy]* ) + BACKUP_DIR=$(get_backup_dirname) + mv "$DIRPATH_QS" "$DIRPATH_QS-backup-$BACKUP_DIR" 2>&1 | tee -a "$LOG" + echo -e "${NOTE} - Backed up quickshell to $DIRPATH_QS-backup-$BACKUP_DIR" + + cp -r "config/quickshell/" "$DIRPATH_QS" 2>&1 | tee -a "$LOG" + if [ $? -eq 0 ]; then + echo "${OK} - ${YELLOW}quickshell${RESET} overwritten successfully." + else + echo "${ERROR} - Failed to copy ${YELLOW}quickshell${RESET} config." + exit 1 + fi + ;; + * ) + echo "${NOTE} - Skipping overwrite of quickshell config." + ;; + esac + fi +fi +printf "\n%.0s" {1..1} + + # Restore automatically Animations and Monitor-Profiles # including monitors.conf and workspaces.conf HYPR_DIR="$HOME/.config/hypr" @@ -1037,4 +1074,4 @@ printf "\n%.0s" {1..1} printf "${INFO} However, it is ${MAGENTA}HIGHLY SUGGESTED${RESET} to logout and re-login or better reboot to avoid any issues" printf "\n%.0s" {1..1} printf "${SKY_BLUE}Thank you${RESET} for using ${MAGENTA}KooL's Hyprland Configuration${RESET}... ${YELLOW}ENJOY!!!${RESET}" -printf "\n%.0s" {1..3} +printf "\n%.0s" {1..3} \ No newline at end of file -- cgit v1.2.3 From 705361b4cee35d61b649f3b1be0e832de811c1b0 Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Wed, 16 Jul 2025 07:20:36 +0900 Subject: adjusted copy.sh to work with simple_sddm_2 --- copy.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'copy.sh') diff --git a/copy.sh b/copy.sh index d7d29806..f5e0e982 100755 --- a/copy.sh +++ b/copy.sh @@ -929,11 +929,11 @@ rm -rf "$HOME/.config/waybar/configs/[TOP] Default$config_remove" \ printf "\n%.0s" {1..1} -# for SDDM (sequoia_2) -sddm_sequioa="/usr/share/sddm/themes/sequoia_2" -if [ -d "$sddm_sequioa" ]; then +# for SDDM (simple_sddm_2) +sddm_simple_sddm_2="/usr/share/sddm/themes/simple_sddm_2" +if [ -d "$sddm_simple_sddm_2" ]; then while true; do - echo -n "${CAT} SDDM sequoia_2 theme detected! Apply current wallpaper as SDDM background? (y/n): " + echo -n "${CAT} SDDM simple_sddm_2 theme detected! Apply current wallpaper as SDDM background? (y/n): " read SDDM_WALL # Remove any leading/trailing whitespace or newlines from input @@ -942,7 +942,7 @@ if [ -d "$sddm_sequioa" ]; then case $SDDM_WALL in [Yy]) # Copy the wallpaper, ignore errors if the file exists or fails - sudo cp -r "config/hypr/wallpaper_effects/.wallpaper_current" "/usr/share/sddm/themes/sequoia_2/backgrounds/default" || true + sudo cp -r "config/hypr/wallpaper_effects/.wallpaper_current" "/usr/share/sddm/themes/simple_sddm_2/backgrounds/default" || true echo "${NOTE} Current wallpaper applied as default SDDM background" 2>&1 | tee -a "$LOG" break ;; -- cgit v1.2.3 From 67928e6b56703b02777061a38602c40f32d6a9aa Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Wed, 16 Jul 2025 22:14:19 +0900 Subject: updated sddm --- copy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'copy.sh') diff --git a/copy.sh b/copy.sh index f5e0e982..1c28f7a6 100755 --- a/copy.sh +++ b/copy.sh @@ -942,7 +942,7 @@ if [ -d "$sddm_simple_sddm_2" ]; then case $SDDM_WALL in [Yy]) # Copy the wallpaper, ignore errors if the file exists or fails - sudo cp -r "config/hypr/wallpaper_effects/.wallpaper_current" "/usr/share/sddm/themes/simple_sddm_2/backgrounds/default" || true + sudo cp -r "config/hypr/wallpaper_effects/.wallpaper_current" "/usr/share/sddm/themes/simple_sddm_2/Backgrounds/default" || true echo "${NOTE} Current wallpaper applied as default SDDM background" 2>&1 | tee -a "$LOG" break ;; -- cgit v1.2.3 From cc779038f9ef892b487963e6f71ea9b4f17a49b9 Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Thu, 17 Jul 2025 22:16:55 +0900 Subject: updated quick shell config copy --- copy.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'copy.sh') diff --git a/copy.sh b/copy.sh index 1c28f7a6..481b3832 100755 --- a/copy.sh +++ b/copy.sh @@ -666,16 +666,16 @@ done printf "\n%.0s" {1..1} # quickshell (ags alternative) -# Check if quickshell is running -if pgrep -x "qs" >/dev/null; then - echo -e "${NOTE} - ${YELLOW}quickshell${RESET} is currently installed and running." +# Check if quickshell is installed +if command -v qs >/dev/null 2>&1; then + echo -e "${NOTE} - ${YELLOW}quickshell${RESET} is detected as installed" DIRPATH_QS="$HOME/.config/quickshell" if [ ! -d "$DIRPATH_QS" ]; then echo "${INFO} - quickshell config not found, copying new config." if [ -d "config/quickshell" ]; then - cp -r "config/quickshell/" "$DIRPATH" 2>&1 | tee -a "$LOG" + cp -r "config/quickshell/" "$DIRPATH_QS" 2>&1 | tee -a "$LOG" fi else read -p "${CAT} Do you want to overwrite your existing ${YELLOW}quickshell${RESET} config? [y/N] " answer_qs @@ -684,7 +684,7 @@ if pgrep -x "qs" >/dev/null; then BACKUP_DIR=$(get_backup_dirname) mv "$DIRPATH_QS" "$DIRPATH_QS-backup-$BACKUP_DIR" 2>&1 | tee -a "$LOG" echo -e "${NOTE} - Backed up quickshell to $DIRPATH_QS-backup-$BACKUP_DIR" - + cp -r "config/quickshell/" "$DIRPATH_QS" 2>&1 | tee -a "$LOG" if [ $? -eq 0 ]; then echo "${OK} - ${YELLOW}quickshell${RESET} overwritten successfully." -- cgit v1.2.3 From 3c1cc04020678b76a622a1a7a28a2c1e529f7665 Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Sat, 19 Jul 2025 17:27:14 +0900 Subject: updated copy.sh and still added ags --- config/ags/config.js | 31 ++ config/ags/modules/.configuration/user_options.js | 127 +++++++ config/ags/modules/.miscutils/icons.js | 13 + config/ags/modules/.miscutils/mathfuncs.js | 4 + config/ags/modules/.miscutils/system.js | 54 +++ .../ags/modules/.widgethacks/advancedrevealers.js | 86 +++++ config/ags/modules/.widgethacks/popupwindow.js | 32 ++ config/ags/modules/.widgetutils/clickthrough.js | 4 + config/ags/modules/.widgetutils/cursorhover.js | 57 +++ config/ags/modules/.widgetutils/keybind.js | 25 ++ config/ags/modules/overview/actions.js | 28 ++ config/ags/modules/overview/main.js | 18 + config/ags/modules/overview/miscfunctions.js | 155 ++++++++ config/ags/modules/overview/overview_hyprland.js | 423 +++++++++++++++++++++ config/ags/modules/overview/searchbuttons.js | 163 ++++++++ config/ags/modules/overview/searchitem.js | 65 ++++ config/ags/modules/overview/windowcontent.js | 262 +++++++++++++ config/ags/user/style.css | 197 ++++++++++ config/ags/user_options.js | 21 + config/ags/variables.js | 21 + config/hypr/UserConfigs/Startup_Apps.conf | 1 + config/hypr/UserConfigs/UserKeybinds.conf | 5 +- copy.sh | 60 +++ 23 files changed, 1850 insertions(+), 2 deletions(-) create mode 100644 config/ags/config.js create mode 100644 config/ags/modules/.configuration/user_options.js create mode 100644 config/ags/modules/.miscutils/icons.js create mode 100644 config/ags/modules/.miscutils/mathfuncs.js create mode 100644 config/ags/modules/.miscutils/system.js create mode 100644 config/ags/modules/.widgethacks/advancedrevealers.js create mode 100644 config/ags/modules/.widgethacks/popupwindow.js create mode 100644 config/ags/modules/.widgetutils/clickthrough.js create mode 100644 config/ags/modules/.widgetutils/cursorhover.js create mode 100644 config/ags/modules/.widgetutils/keybind.js create mode 100644 config/ags/modules/overview/actions.js create mode 100644 config/ags/modules/overview/main.js create mode 100644 config/ags/modules/overview/miscfunctions.js create mode 100644 config/ags/modules/overview/overview_hyprland.js create mode 100644 config/ags/modules/overview/searchbuttons.js create mode 100644 config/ags/modules/overview/searchitem.js create mode 100644 config/ags/modules/overview/windowcontent.js create mode 100644 config/ags/user/style.css create mode 100644 config/ags/user_options.js create mode 100644 config/ags/variables.js (limited to 'copy.sh') 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..242c0575 --- /dev/null +++ b/config/ags/modules/.configuration/user_options.js @@ -0,0 +1,127 @@ + +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: { + 'codium-url-handler': "vscodium", + 'codium': "vscodium", + '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", + 'eu.betterbird.Betterbird' : "thunderbird", + 'thunderbird-esr': "thunderbird", + 'wps': "wps-office2019-kprometheus", + 'wpsoffice': "wps-office2019-kprometheus", + 'firefox-esr': "firefox", + 'soffice' : "libreoffice", + '': "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..13410ea4 --- /dev/null +++ b/config/ags/user/style.css @@ -0,0 +1,197 @@ +*:not(popover) { + all: unset; +} + +@import '../../../.config/waybar/wallust/colors-waybar.css'; + +/* define some colors */ +@define-color border-color @color12; +@define-color border-color-alt @color9; +@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: 4px solid @border-color; + border-left: 1px solid @border-color-alt; + border-right: 1px solid @border-color-alt; + border-bottom: 4px solid @border-color; + box-shadow: 0px 2px 3px alpha(@color12, 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: 4px solid @border-color; + border-left: 1px solid @border-color-alt; + border-right: 1px solid @border-color-alt; + border-bottom: 4px 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: 4px solid @border-color; + border-left: 1px solid @border-color-alt; + border-right: 1px solid @border-color-alt; + border-bottom: 4px 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..645a5807 --- /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 "hyprctl monitors -j | jq '.[0].width / .[0].scale'"`)); +export const SCREEN_HEIGHT = Number(exec(`bash -c "hyprctl monitors -j | jq '.[0].height / .[0].scale'"`)); + +// 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 63f2ee68..f8af55e4 100644 --- a/config/hypr/UserConfigs/Startup_Apps.conf +++ b/config/hypr/UserConfigs/Startup_Apps.conf @@ -26,6 +26,7 @@ exec-once = $scriptsDir/Polkit.sh # starup apps exec-once = nm-applet --indicator exec-once = swaync +#exec-once = ags #exec-once = blueman-applet #exec-once = rog-control-center exec-once = waybar diff --git a/config/hypr/UserConfigs/UserKeybinds.conf b/config/hypr/UserConfigs/UserKeybinds.conf index c92352fc..70202ba4 100644 --- a/config/hypr/UserConfigs/UserKeybinds.conf +++ b/config/hypr/UserConfigs/UserKeybinds.conf @@ -12,13 +12,14 @@ $UserScripts = $HOME/.config/hypr/UserScripts $UserConfigs = $HOME/.config/hypr/UserConfigs # settings for User defaults apps - set your default terminal and file manager on this file -source= $UserConfigs/01-UserDefaults.conf +source= $UserConfigs/01-UserDefaults.conf # common shortcuts #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 || true && rofi -show drun -modi drun,filebrowser,run,window # Main Menu (APP Launcher) bind = $mainMod, B, exec, xdg-open "https://" # default browser -bind = $mainMod, A, global, quickshell:overviewToggle # desktop overview (if installed) +#bind = $mainMod, A, exec, pkill rofi || true && ags -t 'overview' # desktop overview (if installed) +#bind = $mainMod, A, global, quickshell:overviewToggle # desktop overview (if installed) bind = $mainMod, Return, exec, $term #terminal bind = $mainMod, E, exec, $files #file manager diff --git a/copy.sh b/copy.sh index 481b3832..e2c06bc1 100755 --- a/copy.sh +++ b/copy.sh @@ -235,13 +235,37 @@ if command -v blueman-applet >/dev/null 2>&1; then sed -i '/^\s*#exec-once = blueman-applet/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf fi +# Check if ags is installed edit ags behaviour on configs +if command -v ags >/dev/null 2>&1; then + sed -i '/^\s*#exec-once = ags/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf + sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh + sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/Refresh.sh + + # Uncomment the ags overview keybind (tolerates spaces/tabs) + sed -i '/^\s*#\s*bind\s*=\s*\$mainMod,\s*A,\s*exec,\s*pkill rofi\s*\|\|\s*true\s*&&\s*ags\s*-t\s*'\''overview'\''/s/^\s*#\s*//' config/hypr/UserConfigs/UserKeybinds.conf + + # Comment the quickshell line if not already commented (tolerates spaces/tabs) + sed -i '/^\s*bind\s*=\s*\$mainMod,\s*A,\s*global,\s*quickshell:overviewToggle/{ + s/^\s*/#/ + }' config/hypr/UserConfigs/UserKeybinds.conf +fi + # Check if quickshell is installed edit quickshell behaviour on configs if command -v qs >/dev/null 2>&1; then sed -i '/^\s*#exec-once = qs/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/Refresh.sh + + # Uncomment the quickshell keybind line (tolerates spaces/tabs) + sed -i '/^\s*#\s*bind\s*=\s*\$mainMod,\s*A,\s*global,\s*quickshell:overviewToggle/s/^\s*#\s*//' config/hypr/UserConfigs/UserKeybinds.conf + + # Ensure the ags overview keybind is commented (tolerates spaces/tabs) + sed -i '/^\s*bind\s*=\s*\$mainMod,\s*A,\s*exec,\s*pkill rofi\s*\|\|\s*true\s*&&\s*ags\s*-t\s*'\''overview'\''/{ + s/^\s*/#/ + }' config/hypr/UserConfigs/UserKeybinds.conf fi + printf "\n%.0s" {1..1} # Checking if neovim or vim is installed and offer user if they want to make as default editor @@ -665,6 +689,42 @@ done printf "\n%.0s" {1..1} +# ags config +# Check if ags is installed +if command -v ags >/dev/null 2>&1; then + echo -e "${NOTE} - ${YELLOW}ags${RESET} is detected as installed" + + DIRPATH_AGS="$HOME/.config/ags" + + if [ ! -d "$DIRPATH_AGS" ]; then + echo "${INFO} - ags config not found, copying new config." + if [ -d "config/ags" ]; then + cp -r "config/ags/" "$DIRPATH_AGS" 2>&1 | tee -a "$LOG" + fi + else + read -p "${CAT} Do you want to overwrite your existing ${YELLOW}ags${RESET} config? [y/N] " answer_ags + case "$answer_ags" in + [Yy]* ) + BACKUP_DIR=$(get_backup_dirname) + mv "$DIRPATH_AGS" "$DIRPATH_AGS-backup-$BACKUP_DIR" 2>&1 | tee -a "$LOG" + echo -e "${NOTE} - Backed up ags config to $DIRPATH_AGS-backup-$BACKUP_DIR" + + if cp -r "config/ags/" "$DIRPATH_AGS" 2>&1 | tee -a "$LOG"; then + echo "${OK} - ${YELLOW}ags configs${RESET} overwritten successfully." + else + echo "${ERROR} - Failed to copy ${YELLOW}ags${RESET} config." + exit 1 + fi + ;; + * ) + echo "${NOTE} - Skipping overwrite of ags config." + ;; + esac + fi +fi + +printf "\n%.0s" {1..1} + # quickshell (ags alternative) # Check if quickshell is installed if command -v qs >/dev/null 2>&1; then -- cgit v1.2.3 From a065ed1fcfcffd9eddbd3c4c848da1f6c6ae9dd0 Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Sat, 19 Jul 2025 20:24:26 +0900 Subject: Fixed the uncommenting part of UserKeybinds.conf --- copy.sh | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'copy.sh') diff --git a/copy.sh b/copy.sh index e2c06bc1..3677c86e 100755 --- a/copy.sh +++ b/copy.sh @@ -241,31 +241,26 @@ if command -v ags >/dev/null 2>&1; then sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh sed -i '/#ags -q && ags &/s/^#//' config/hypr/scripts/Refresh.sh - # Uncomment the ags overview keybind (tolerates spaces/tabs) - sed -i '/^\s*#\s*bind\s*=\s*\$mainMod,\s*A,\s*exec,\s*pkill rofi\s*\|\|\s*true\s*&&\s*ags\s*-t\s*'\''overview'\''/s/^\s*#\s*//' config/hypr/UserConfigs/UserKeybinds.conf + # Uncomment the ags overview keybind + sed -i '/^#bind = \$mainMod, A, exec, pkill rofi || true && ags -t '\''overview'\''/s/^#//' config/hypr/UserConfigs/UserKeybinds.conf - # Comment the quickshell line if not already commented (tolerates spaces/tabs) - sed -i '/^\s*bind\s*=\s*\$mainMod,\s*A,\s*global,\s*quickshell:overviewToggle/{ - s/^\s*/#/ - }' config/hypr/UserConfigs/UserKeybinds.conf + # Comment the quickshell line if not already commented + sed -i '/^\s*bind\s*=\s*\$mainMod,\s*A,\s*global,\s*quickshell:overviewToggle/{s/^\s*/#/}' config/hypr/UserConfigs/UserKeybinds.conf fi -# Check if quickshell is installed edit quickshell behaviour on configs +# Check if quickshell is installed; edit quickshell behaviour on configs if command -v qs >/dev/null 2>&1; then sed -i '/^\s*#exec-once = qs/s/^#//' config/hypr/UserConfigs/Startup_Apps.conf sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/RefreshNoWaybar.sh sed -i '/#pkill qs && qs &/s/^#//' config/hypr/scripts/Refresh.sh - # Uncomment the quickshell keybind line (tolerates spaces/tabs) - sed -i '/^\s*#\s*bind\s*=\s*\$mainMod,\s*A,\s*global,\s*quickshell:overviewToggle/s/^\s*#\s*//' config/hypr/UserConfigs/UserKeybinds.conf + # Uncomment the quickshell keybind line + sed -i "/^#bind = \$mainMod, A, global, quickshell:overviewToggle/s/^#//" config/hypr/UserConfigs/UserKeybinds.conf - # Ensure the ags overview keybind is commented (tolerates spaces/tabs) - sed -i '/^\s*bind\s*=\s*\$mainMod,\s*A,\s*exec,\s*pkill rofi\s*\|\|\s*true\s*&&\s*ags\s*-t\s*'\''overview'\''/{ - s/^\s*/#/ - }' config/hypr/UserConfigs/UserKeybinds.conf + # Ensure the ags overview keybind is commented + sed -i "/^\s*bind\s*=\s*\\\$mainMod,\s*A,\s*exec,\s*pkill rofi\s*||\s*true\s*&&\s*ags\s*-t\s*'overview'/{s/^\s*/#/}" config/hypr/UserConfigs/UserKeybinds.conf fi - printf "\n%.0s" {1..1} # Checking if neovim or vim is installed and offer user if they want to make as default editor -- cgit v1.2.3 From 54af0ed84c6efcf61f088ab1af1188842aa4ed0d Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Tue, 22 Jul 2025 00:13:48 +0900 Subject: updated copy.sh to work with simple_sddm_2 and updated wallpaper_sddm script --- config/hypr/scripts/sddm_wallpaper-v2.sh | 82 +++++++++++++++----------------- copy.sh | 2 +- 2 files changed, 39 insertions(+), 45 deletions(-) (limited to 'copy.sh') diff --git a/config/hypr/scripts/sddm_wallpaper-v2.sh b/config/hypr/scripts/sddm_wallpaper-v2.sh index 898053c7..19fe7158 100644 --- a/config/hypr/scripts/sddm_wallpaper-v2.sh +++ b/config/hypr/scripts/sddm_wallpaper-v2.sh @@ -28,55 +28,49 @@ elif [[ "$1" == "--effects" ]]; then mode="effects" fi - - # Extract colors from rofi wallust config -get_color() { - grep -oP "$1:\s*\K#[A-Fa-f0-9]+" "$rofi_wallust" -} - -color11=$(get_color 'color11') -HeaderTextColor=$(get_color 'color12') -DateTextColor=$(get_color 'color13') -bg_color=$(get_color 'color0') -placeholder_color="$accent_color" -icon_color=$(get_color 'foreground') -color11=$(get_color 'color11') +color14=$(grep -oP 'color14:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +color13=$(grep -oP 'color13:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +color12=$(grep -oP 'color12:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +color1=$(grep -oP 'color1:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +color0=$(grep -oP 'color0:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +color10=$(grep -oP 'color10:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +foreground=$(grep -oP 'foreground:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") +#background-color=$(grep -oP 'background:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust") -# Define an array of key-value pairs for SDDM config updates -declare -A color_updates=( - [HeaderTextColor]="$HeaderTextColor" - [DateTextColor]="$DateTextColor" - [TimeTextColor]="$DateTextColor" - [SystemButtonsIconsColor]="$DateTextColor" - [SessionButtonTextColor]="$DateTextColor" - [VirtualKeyboardButtonTextColor]="$DateTextColor" - [BackgroundColor]="$bg_color" - [PlaceholderTextColor]="$placeholder_color" - [IconColor]="$icon_color" - [DropdownBackgroundColor]="$bg_color" - [HighlightBackgroundColor]="$color11" -) +# wallpaper to use +if [[ "$mode" == "normal" ]]; then + wallpaper_path="$wallpaper_current" +else + wallpaper_path="$wallpaper_modified" +fi -# Apply changes via terminal and sudo +# Launch terminal and apply changes $terminal -e bash -c " echo 'Enter your password to update SDDM wallpapers and colors'; -$(for key in "${!color_updates[@]}"; do - value="${color_updates[$key]}" - echo "sudo sed -i \"s/${key}=\\\"#.*\\\"/${key}=\\\"$value\\\"/\" \"$sddm_theme_conf\"" -done) -" -# Set wallpaper path based on mode -wallpaper_path=$([[ "$mode" == "normal" ]] && echo "$wallpaper_current" || echo "$wallpaper_modified") +# Update the colors in the SDDM config +sudo sed -i \"s/HeaderTextColor=\\\"#.*\\\"/HeaderTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/DateTextColor=\\\"#.*\\\"/DateTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/TimeTextColor=\\\"#.*\\\"/TimeTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/DropdownSelectedBackgroundColor=\\\"#.*\\\"/DropdownSelectedBackgroundColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -# Copy wallpaper safely -if [[ -f "$wallpaper_path" ]]; then - sudo cp "$wallpaper_path" "$sddm_simple/Backgrounds/default" - notify-send -i "$iDIR/ja.png" "SDDM" "Background SET" -else - notify-send -i "$iDIR/ja.png" "SDDM" "Wallpaper not found: $wallpaper_path" - echo "Error: Wallpaper file not found: $wallpaper_path" - exit 1 -fi +sudo sed -i \"s/SystemButtonsIconsColor=\\\"#.*\\\"/SystemButtonsIconsColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/SessionButtonTextColor=\\\"#.*\\\"/SessionButtonTextColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/VirtualKeyboardButtonTextColor=\\\"#.*\\\"/VirtualKeyboardButtonTextColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/HighlightBackgroundColor=\\\"#.*\\\"/HighlightBackgroundColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/LoginFieldTextColor=\\\"#.*\\\"/LoginFieldTextColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/PasswordFieldTextColor=\\\"#.*\\\"/PasswordFieldTextColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" + +sudo sed -i \"s/DropdownBackgroundColor=\\\"#.*\\\"/DropdownBackgroundColor=\\\"$color0\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/HighlightTextColor=\\\"#.*\\\"/HighlightTextColor=\\\"$color10\\\"/\" \"$sddm_theme_conf\" + +sudo sed -i \"s/PlaceholderTextColor=\\\"#.*\\\"/PlaceholderTextColor=\\\"$color14\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/UserIconColor=\\\"#.*\\\"/UserIconColor=\\\"$color14\\\"/\" \"$sddm_theme_conf\" +sudo sed -i \"s/PasswordIconColor=\\\"#.*\\\"/PasswordIconColor=\\\"$color14\\\"/\" \"$sddm_theme_conf\" + +# Copy wallpaper to SDDM theme +sudo cp \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default\" +notify-send -i \"$iDIR/ja.png\" \"SDDM\" \"Background SET\" +" \ No newline at end of file diff --git a/copy.sh b/copy.sh index 3677c86e..b3e001bd 100755 --- a/copy.sh +++ b/copy.sh @@ -406,7 +406,7 @@ while true; do # Applying to different SDDM themes apply_sddm_12h_format "/usr/share/sddm/themes/simple-sddm" - apply_sddm_12h_format "/usr/share/sddm/themes/simple-sddm-2" + apply_sddm_12h_format "/usr/share/sddm/themes/simple_sddm_2" # For SDDM (sequoia_2) sddm_directory_3="/usr/share/sddm/themes/sequoia_2" -- cgit v1.2.3 From badd7e251e526138840a5f513876453372c243ca Mon Sep 17 00:00:00 2001 From: JaKooLit Date: Tue, 22 Jul 2025 01:15:43 +0900 Subject: added env = GSK_RENDERER,ngl for nvidia --- config/hypr/UserConfigs/ENVariables.conf | 1 + copy.sh | 2 ++ 2 files changed, 3 insertions(+) (limited to 'copy.sh') diff --git a/config/hypr/UserConfigs/ENVariables.conf b/config/hypr/UserConfigs/ENVariables.conf index 2f53c74c..f24cc306 100644 --- a/config/hypr/UserConfigs/ENVariables.conf +++ b/config/hypr/UserConfigs/ENVariables.conf @@ -54,6 +54,7 @@ env = ELECTRON_OZONE_PLATFORM_HINT,auto # auto selects Wayland if possible, X11 #env = LIBVA_DRIVER_NAME,nvidia #env = __GLX_VENDOR_LIBRARY_NAME,nvidia #env = NVD_BACKEND,direct +#env = GSK_RENDERER,ngl # additional ENV's for nvidia. Caution, activate with care #env = GBM_BACKEND,nvidia-drm diff --git a/copy.sh b/copy.sh index b3e001bd..5af67f21 100755 --- a/copy.sh +++ b/copy.sh @@ -87,6 +87,8 @@ if lspci -k | grep -A 2 -E "(VGA|3D)" | grep -iq nvidia; then sed -i '/env = LIBVA_DRIVER_NAME,nvidia/s/^#//' config/hypr/UserConfigs/ENVariables.conf sed -i '/env = __GLX_VENDOR_LIBRARY_NAME,nvidia/s/^#//' config/hypr/UserConfigs/ENVariables.conf sed -i '/env = NVD_BACKEND,direct/s/^#//' config/hypr/UserConfigs/ENVariables.conf + sed -i '/env = GSK_RENDERER,ngl/s/^#//' config/hypr/UserConfigs/ENVariables.conf + # no hardware cursors if nvidia detected sed -i 's/^\([[:space:]]*no_hardware_cursors[[:space:]]*=[[:space:]]*\)2/\1 1/' config/hypr/UserConfigs/UserSettings.conf #sed -i 's/^\([[:space:]]*explicit_sync[[:space:]]*=[[:space:]]*\)2/\1 0/' config/hypr/UserConfigs/UserSettings.conf -- cgit v1.2.3