├── .gitignore ├── LICENSE ├── PKGBUILD ├── README.md ├── screenshots ├── sleex1.png ├── sleex2.png ├── sleex3.png └── sleex4.png ├── sleex_presentation.mp4 └── src ├── bin ├── fuzzel-emoji ├── rubyshot └── sleex └── share ├── sleex ├── .idea │ ├── .gitignore │ ├── modules.xml │ └── sleex.iml ├── assets │ ├── icons │ │ ├── ai-openai-symbolic.svg │ │ ├── ai-oxygen-symbolic.svg │ │ ├── ai-zukijourney.png │ │ ├── arch-symbolic.svg │ │ ├── axos-symbolic.svg │ │ ├── cachyos-symbolic.svg │ │ ├── cloudflare-dns-symbolic.svg │ │ ├── crosshair-symbolic.svg │ │ ├── debian-symbolic.svg │ │ ├── endeavouros-symbolic.svg │ │ ├── fedora-symbolic.svg │ │ ├── flatpak-symbolic.svg │ │ ├── github-symbolic.svg │ │ ├── google-gemini-symbolic.svg │ │ ├── linux-symbolic.svg │ │ ├── mona-loading.gif │ │ ├── nixos-symbolic.svg │ │ ├── ollama-symbolic.svg │ │ ├── openai-symbolic.svg │ │ ├── openrouter-symbolic.svg │ │ ├── ubuntu-symbolic.svg │ │ └── weather │ │ │ ├── weather-clear-night.svg │ │ │ ├── weather-clear-sky.svg │ │ │ ├── weather-clouds-night.svg │ │ │ ├── weather-clouds.svg │ │ │ ├── weather-few-clouds-night.svg │ │ │ ├── weather-few-clouds.svg │ │ │ ├── weather-fog.svg │ │ │ ├── weather-freezing-rain.svg │ │ │ ├── weather-overcast-symbolic.svg │ │ │ ├── weather-overcast.svg │ │ │ ├── weather-showers-scattered.svg │ │ │ ├── weather-showers.svg │ │ │ ├── weather-snow-rain.svg │ │ │ ├── weather-snow-scattered.svg │ │ │ ├── weather-snow.svg │ │ │ ├── weather-storm.svg │ │ │ └── weather-windy.svg │ ├── no_music.png │ └── themes │ │ ├── sourceviewtheme-dark-monokai-license.txt │ │ ├── sourceviewtheme-light.xml │ │ └── sourceviewtheme.xml ├── config.js ├── config_overviewOnly.js ├── init.js ├── modules │ ├── .commondata │ │ ├── hyprlanddata.js │ │ ├── quotes.js │ │ └── weather.js │ ├── .commonwidgets │ │ ├── cairo_circularprogress.js │ │ ├── cairo_navigationindicator.js │ │ ├── cairo_roundedcorner.js │ │ ├── cairo_slider.js │ │ ├── clickcloseregion.js │ │ ├── configwidgets.js │ │ ├── materialicon.js │ │ ├── notification.js │ │ ├── statusicons.js │ │ ├── statusicons_languages.js │ │ ├── tabcontainer.js │ │ └── vertical_tabcontainer.js │ ├── .configuration │ │ ├── default_config.json │ │ └── user_options.js │ ├── .miscutils │ │ ├── files.js │ │ ├── icons.js │ │ ├── mathfuncs.js │ │ ├── md2pango.js │ │ └── system.js │ ├── .widgethacks │ │ ├── advancedrevealers.js │ │ └── popupwindow.js │ ├── .widgetutils │ │ ├── clickthrough.js │ │ ├── cursorhover.js │ │ └── keybind.js │ ├── bar │ │ ├── focus │ │ │ ├── workspaces_hyprland.js │ │ │ └── workspaces_sway.js │ │ ├── main.js │ │ └── normal │ │ │ ├── monitor.js │ │ │ ├── music.js │ │ │ ├── spaceleft.js │ │ │ ├── spaceright.js │ │ │ ├── system.js │ │ │ ├── tray.js │ │ │ ├── weather.js │ │ │ ├── workspaces_box.js │ │ │ ├── workspaces_hyprland.js │ │ │ └── workspaces_sway.js │ ├── cheatsheet │ │ ├── data_keybinds.js │ │ ├── data_periodictable.js │ │ ├── globalinfo.js │ │ ├── keybinds.js │ │ ├── main.js │ │ └── periodictable.js │ ├── dashboard │ │ ├── calendar.js │ │ ├── calendar_layout.js │ │ ├── centermodules │ │ │ ├── audiocontrols.js │ │ │ ├── bluetooth.js │ │ │ ├── configure.js │ │ │ ├── notificationlist.js │ │ │ └── wifinetworks.js │ │ ├── dashboard.js │ │ ├── dashboard_bak.js │ │ ├── main.js │ │ ├── music.js │ │ ├── name.js │ │ ├── quicktoggles.js │ │ ├── quote.js │ │ ├── tabs │ │ │ ├── apiwidgets.js │ │ │ ├── home.js │ │ │ ├── settings.js │ │ │ ├── todo.js │ │ │ └── updates.js │ │ ├── todolist.js │ │ ├── weather.js │ │ └── widgets │ │ │ ├── apis │ │ │ ├── ai_chatmessage.js │ │ │ ├── chatgpt.js │ │ │ └── gemini.js │ │ │ ├── calendar.js │ │ │ ├── calendar_layout.js │ │ │ ├── clock.js │ │ │ ├── github.js │ │ │ ├── music.js │ │ │ ├── name.js │ │ │ ├── quicktoggles.js │ │ │ ├── quote.js │ │ │ ├── timer.js │ │ │ ├── todo_tag.js │ │ │ ├── todolist.js │ │ │ ├── user_widget.js │ │ │ └── weather.js │ ├── desktopbackground │ │ ├── data_quicklaunches.js │ │ ├── main.js │ │ ├── system.js │ │ ├── timeandlaunches.js │ │ └── wallpaper.js │ ├── indicators │ │ ├── colorscheme.js │ │ ├── indicatorvalueBrightness.js │ │ ├── indicatorvalues.js │ │ ├── indicatorvaluesAudio.js │ │ ├── main.js │ │ ├── musiccontrols.js │ │ └── notificationpopups.js │ ├── lockscreen │ │ ├── auth.py │ │ └── main.js │ ├── overview │ │ ├── actions.js │ │ ├── main.js │ │ ├── miscfunctions.js │ │ ├── overview_hyprland.js │ │ ├── searchbuttons.js │ │ ├── searchitem.js │ │ └── windowcontent.js │ ├── session │ │ ├── main.js │ │ └── sessionscreen.js │ ├── sideleft │ │ ├── apis │ │ │ ├── ai_chatmessage.js │ │ │ ├── chatgpt.js │ │ │ └── gemini.js │ │ ├── apiwidgets.js │ │ ├── main.js │ │ ├── sideleft.js │ │ └── updates.js │ └── wallselect │ │ └── main.js ├── scripts │ ├── README.md │ ├── color_generation │ │ ├── applycolor.sh │ │ ├── colorgen.sh │ │ ├── generate_colors_material.py │ │ ├── pywal_to_material.scss │ │ ├── randomwall.sh │ │ ├── schemes │ │ │ ├── __pycache__ │ │ │ │ └── scheme_morevibrant.cpython-313.pyc │ │ │ └── scheme_morevibrant.py │ │ ├── specials │ │ │ ├── _material_badapple-l.scss │ │ │ └── _material_badapple.scss │ │ ├── switchcolor.sh │ │ └── switchwall.sh │ ├── dnd.sh │ ├── firstRun.sh │ ├── generate_thumbnails.sh │ ├── grimblast.sh │ ├── hyprland │ │ ├── get_keybinds.py │ │ └── workspace_action.sh │ ├── lockscreen │ │ ├── battery-status │ │ └── song-status │ ├── network_scripts │ │ └── network_bandwidth.py │ ├── quickscripts │ │ └── nixos-trim-generations.sh │ ├── record-script.sh │ ├── sway │ │ └── swayToRelativeWs.sh │ ├── templates │ │ ├── fuzzel │ │ │ └── fuzzel.ini │ │ ├── gradience │ │ │ └── preset.json │ │ ├── gtk │ │ │ └── gtk-colors.css │ │ └── terminal │ │ │ ├── scheme-base.json │ │ │ ├── scheme-monochrome.json │ │ │ └── sequences.txt │ └── wayland-idle-inhibitor.py ├── scss │ ├── _bar.scss │ ├── _cheatsheet.scss │ ├── _colors.scss │ ├── _common.scss │ ├── _desktopbackground.scss │ ├── _dock.scss │ ├── _lib_classes.scss │ ├── _lib_mixins.scss │ ├── _lockscreen.scss │ ├── _music.scss │ ├── _notifications.scss │ ├── _osd.scss │ ├── _osk.scss │ ├── _overview.scss │ ├── _session.scss │ ├── _sidebars.scss │ ├── _wal.scss │ ├── _wallpaper.scss │ ├── fallback │ │ └── _material.scss │ └── main.scss ├── services │ ├── brightness.js │ ├── darkmode.js │ ├── gemini.js │ ├── globalinfo.js │ ├── gpt.js │ ├── indicator.js │ ├── lockscreen.js │ ├── messages.js │ ├── sway.js │ ├── timers.js │ ├── todo.js │ ├── wallpaper.js │ └── weather.js ├── user_options.js ├── variables.js └── wallpapers │ ├── aesthetic_deer.jpg │ ├── apple-light.jpg │ ├── building_cyber.jpg │ ├── city-rain.png │ ├── city-skyline.jpg │ ├── city.gif │ ├── deer_and_sunset.jpg │ ├── earth-from-moon.jpg │ ├── escape_velocity.jpg │ ├── evening-landscape.jpg │ ├── explorer_green_day.jpg │ ├── explorer_orange_sunset.jpg │ ├── highlands-grid.jpg │ ├── landscape-abstract-neon.jpg │ ├── lofoten-sundown.jpg │ ├── lofoten2.jpg │ ├── loupe-mono-dark-preview.png │ ├── midnight-reflections-moonlit-sea.jpg │ ├── moonlight.jpg │ ├── mountain-lake.jpg │ ├── mountain-sunrise.jpg │ ├── mountain-winter1.jpg │ ├── mountain-winter3.jpg │ ├── mountain_view.jpg │ ├── nordwall3.jpg │ ├── oldhouse.gif │ └── sakura.png └── wayland-sessions └── sleex.desktop /.gitignore: -------------------------------------------------------------------------------- 1 | *.tar.zst 2 | pkg/ -------------------------------------------------------------------------------- /PKGBUILD: -------------------------------------------------------------------------------- 1 | pkgname="sleex" 2 | pkgver="0.28" 3 | pkgrel="1" 4 | pkgdesc="Third desktop environment for AxOS" 5 | arch=("x86_64") 6 | depends=( 7 | "sleex-ags" 8 | "sleex-audio" 9 | "sleex-backlight" 10 | "sleex-basic" 11 | "sleex-bibata-modern-classic-bin" 12 | "sleex-fonts-themes" 13 | "sleex-gnome" 14 | "sleex-gtk" 15 | "sleex-microtex-git" 16 | "sleex-oneui4-icons-git" 17 | "sleex-portal" 18 | "sleex-pymyc-aur" 19 | "sleex-python" 20 | "sleex-screencapture" 21 | "sleex-widgets" 22 | "axskel-hypr" 23 | "axctl" 24 | "sleex-control-center" 25 | "hyprland" 26 | ) 27 | optdepends=( 28 | "sleex-optional: Optional packages" 29 | ) 30 | 31 | 32 | package() { 33 | mkdir -p "$pkgdir/usr/" 34 | cp -r "$srcdir/bin" "$pkgdir/usr/" 35 | cp -r "$srcdir/share" "$pkgdir/usr/" 36 | } 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sleex 2 | 3 | Sleex is the third desktop environement of AxOS. It is based on Hyprland with AGS V1. 4 | 5 | ## Features 6 | - Fast and lightweight 7 | - AI chat integration with external providers (Gemini, OpenAI...) 8 | - Smooth animations 9 | - Tiling window management for seamless multitasking 10 | - Adaptative color scheme based on the wallpaper 11 | 12 | ## Screenshots 13 | 14 | | Description | Image | 15 | |--------------------------|-----------------------------------------| 16 | | Video showcase | ![sleex_presentation](sleex_presentation.mp4) | 17 | | Main desktop, adaptative colors according to wallpaper | ![Sleex 1](https://github.com/user-attachments/assets/7cedf067-534b-4104-b934-fcbbd7e606ce) | 18 | | Dashboard with numerous widgets | ![Sleex Dashboard](https://github.com/user-attachments/assets/63697565-d2e3-48c1-91fc-0dcb992fd29f) | 19 | | Wallpaper selector | ![Sleex 3](https://github.com/user-attachments/assets/606bac78-fc89-4700-8a4a-a8676a9bad74) | 20 | | Left panel with LLM APIs and Sleex update center | ![Sleex Side Left](https://github.com/user-attachments/assets/771c918f-0fbc-4c41-82f2-7b03b3c782a4) | 21 | | Workspace overviews with search bar | ![Sleex Overview](https://github.com/user-attachments/assets/98ddc08d-ddeb-43ee-8546-b337d3d29360) | 22 | 23 | ## Installation 24 | 25 | > [!IMPORTANT] 26 | > If you are not using AxOS, you can't install Sleex. 27 | 28 | ```bash 29 | epsi install sleex 30 | ``` 31 | 32 | ## License 33 | Sleex is licensed under the GNU General Public License v3.0 34 | 35 | ## Credits 36 | - [@end-4](https://github.com/end-4) for the base of this rice. 37 | -------------------------------------------------------------------------------- /screenshots/sleex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/screenshots/sleex1.png -------------------------------------------------------------------------------- /screenshots/sleex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/screenshots/sleex2.png -------------------------------------------------------------------------------- /screenshots/sleex3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/screenshots/sleex3.png -------------------------------------------------------------------------------- /screenshots/sleex4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/screenshots/sleex4.png -------------------------------------------------------------------------------- /sleex_presentation.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/sleex_presentation.mp4 -------------------------------------------------------------------------------- /src/bin/rubyshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | WORKSPACES="$(hyprctl monitors -j | jq -r 'map(.activeWorkspace.id)')" 4 | WINDOWS="$(hyprctl clients -j | jq -r --argjson workspaces "$WORKSPACES" 'map(select([.workspace.id] | inside($workspaces)))' )" 5 | GEOM=$(echo "$WINDOWS" | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | slurp -f '%x %y %w %h') 6 | wayshot -s "$GEOM" --stdout ${#:+"$@"} -------------------------------------------------------------------------------- /src/bin/sleex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export XDG_CURRENT_DESKTOP="Sleex" 3 | export HYPRLAND_INSTANCE_SIGNATURE="" 4 | systemctl --user import-environment XDG_CURRENT_DESKTOP 5 | Hyprland 6 | -------------------------------------------------------------------------------- /src/share/sleex/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /src/share/sleex/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/.idea/sleex.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/ai-openai-symbolic.svg: -------------------------------------------------------------------------------- 1 | openai-symbolic.svg -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/ai-oxygen-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 35 | 38 | 43 | 48 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/ai-zukijourney.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/assets/icons/ai-zukijourney.png -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/cloudflare-dns-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/crosshair-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 40 | ionicons-v5_logos 42 | 44 | 45 | 47 | ionicons-v5_logos 48 | 49 | 50 | 51 | 58 | 65 | 66 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/endeavouros-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 41 | EndeavourOS Logo 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | EndeavourOS Logo 52 | 53 | 54 | 55 | 60 | 63 | 66 | 69 | 72 | 75 | 80 | 85 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/fedora-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 34 | 35 | 38 | 39 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/flatpak-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 38 | Flatpak 40 | 43 | 45 | 46 | 48 | Flatpak 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/github-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 33 | 40 | 41 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/google-gemini-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 40 | ionicons-v5_logos 42 | 47 | 49 | 50 | 52 | ionicons-v5_logos 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/mona-loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/assets/icons/mona-loading.gif -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/nixos-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 34 | 39 | 44 | 49 | 54 | 59 | 63 | 67 | 71 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/openrouter-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 34 | 39 | 40 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/ubuntu-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 36 | 39 | 41 | 43 | 46 | 47 | 48 | 50 | 53 | 54 | 56 | 58 | 61 | 62 | 63 | 65 | 68 | 69 | 71 | 73 | 76 | 77 | 78 | 80 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-clear-night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-clear-sky.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-clouds-night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-clouds.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-few-clouds-night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-few-clouds.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-fog.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-freezing-rain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-overcast-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-overcast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-showers-scattered.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-showers.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-snow-rain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-snow-scattered.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-snow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-storm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/share/sleex/assets/icons/weather/weather-windy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/share/sleex/assets/no_music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/assets/no_music.png -------------------------------------------------------------------------------- /src/share/sleex/config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Import 3 | const { GLib } = imports.gi; 4 | import Gdk from 'gi://Gdk'; 5 | import App from 'resource:///com/github/Aylur/ags/app.js' 6 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 7 | const { execAsync } = Utils; 8 | // Stuff 9 | import userOptions from './modules/.configuration/user_options.js'; // Not unused, careful 10 | import { firstRunWelcome, startBatteryWarningService } from './services/messages.js'; 11 | import { startAutoDarkModeService } from './services/darkmode.js'; 12 | import './services/weather.js'; // service that updates weather every 15 minutes 13 | // Widgets 14 | import { Bar } from './modules/bar/main.js'; 15 | import Cheatsheet from './modules/cheatsheet/main.js'; 16 | import DesktopBackground from './modules/desktopbackground/main.js'; 17 | import Indicator from './modules/indicators/main.js'; 18 | import Overview from './modules/overview/main.js'; 19 | import Session from './modules/session/main.js'; 20 | //import SideLeft from './modules/sideleft/main.js'; 21 | import Dashboard from './modules/dashboard/main.js'; 22 | import { COMPILED_STYLE_DIR } from './init.js'; 23 | import Wallselect from './modules/wallselect/main.js'; 24 | import indicatorvalues from './modules/indicators/indicatorvalues.js'; 25 | 26 | const range = (length, start = 1) => Array.from({ length }, (_, i) => i + start); 27 | function forMonitors(widget) { 28 | const n = Gdk.Display.get_default()?.get_n_monitors() || 1; 29 | return range(n, 0).map(widget).flat(1); 30 | } 31 | function forMonitorsAsync(widget) { 32 | const n = Gdk.Display.get_default()?.get_n_monitors() || 1; 33 | return range(n, 0).forEach((n) => widget(n).catch(print)) 34 | } 35 | 36 | const FirstRunScript = () => { 37 | if (!GLib.file_test(`${GLib.get_user_state_dir()}/ags/user/firstrun.txt`, GLib.FileTest.EXISTS)) { 38 | const firstRunScript = `${App.configDir}/scripts/firstRun.sh`; 39 | if (GLib.file_test(firstRunScript, GLib.FileTest.EXISTS)) { 40 | execAsync([firstRunScript]).catch(print); 41 | } 42 | } 43 | } 44 | 45 | // Start stuff 46 | FirstRunScript(); 47 | handleStyles(true); 48 | startAutoDarkModeService().catch(print); 49 | firstRunWelcome().catch(print); 50 | 51 | startBatteryWarningService().catch(print); 52 | 53 | const Windows = () => [ 54 | forMonitors(DesktopBackground), 55 | Overview(), 56 | forMonitors(Indicator), 57 | forMonitors(Cheatsheet), 58 | //SideLeft(), 59 | Dashboard(), 60 | forMonitors(Session), 61 | Wallselect(), 62 | forMonitors(indicatorvalues), 63 | 64 | ]; 65 | 66 | const CLOSE_ANIM_TIME = 210; // Longer than actual anim time to make sure widgets animate fully 67 | const closeWindowDelays = {}; // For animations 68 | for (let i = 0; i < (Gdk.Display.get_default()?.get_n_monitors() || 1); i++) { 69 | } 70 | 71 | App.config({ 72 | css: `${COMPILED_STYLE_DIR}/style.css`, 73 | stackTraceOnError: true, 74 | closeWindowDelay: closeWindowDelays, 75 | windows: Windows().flat(1), 76 | }); 77 | 78 | // Stuff that don't need to be toggled. And they're async so ugh... 79 | forMonitorsAsync(Bar); 80 | // Bar().catch(print); // Use this to debug the bar. Single monitor only. -------------------------------------------------------------------------------- /src/share/sleex/config_overviewOnly.js: -------------------------------------------------------------------------------- 1 | // Import 2 | import App from 'resource:///com/github/Aylur/ags/app.js' 3 | // Widgets 4 | import Overview from './modules/overview/main.js'; 5 | import { COMPILED_STYLE_DIR } from './init.js'; 6 | 7 | handleStyles(true); 8 | 9 | App.config({ 10 | css: `${COMPILED_STYLE_DIR}/style.css`, 11 | stackTraceOnError: true, 12 | windows: [ 13 | Overview(), 14 | ], 15 | }); 16 | -------------------------------------------------------------------------------- /src/share/sleex/init.js: -------------------------------------------------------------------------------- 1 | import GLib from 'gi://GLib'; 2 | import App from 'resource:///com/github/Aylur/ags/app.js' 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' 4 | import { darkMode } from './modules/.miscutils/system.js'; 5 | 6 | export const COMPILED_STYLE_DIR = `${GLib.get_user_cache_dir()}/ags/user/generated` 7 | 8 | globalThis['handleStyles'] = (resetMusic) => { 9 | // Reset 10 | Utils.exec(`mkdir -p "${GLib.get_user_state_dir()}/ags/scss"`); 11 | if (resetMusic) { 12 | Utils.exec(`bash -c 'echo "" > ${GLib.get_user_state_dir()}/ags/scss/_musicwal.scss'`); // reset music styles 13 | Utils.exec(`bash -c 'echo "" > ${GLib.get_user_state_dir()}/ags/scss/_musicmaterial.scss'`); // reset music styles 14 | } 15 | // Generate overrides 16 | let lightdark = darkMode.value ? "dark" : "light"; 17 | Utils.writeFileSync( 18 | `@mixin symbolic-icon { 19 | -gtk-icon-theme: '${userOptions.icons.symbolicIconTheme[lightdark]}'; 20 | } 21 | `, 22 | `${GLib.get_user_state_dir()}/ags/scss/_lib_mixins_overrides.scss`) 23 | // Compile and apply 24 | async function applyStyle() { 25 | Utils.exec(`mkdir -p ${COMPILED_STYLE_DIR}`); 26 | Utils.exec(`sass -I "${GLib.get_user_state_dir()}/ags/scss" -I "${App.configDir}/scss/fallback" "${App.configDir}/scss/main.scss" "${COMPILED_STYLE_DIR}/style.css"`); 27 | App.resetCss(); 28 | App.applyCss(`${COMPILED_STYLE_DIR}/style.css`); 29 | console.log('[LOG] Styles loaded') 30 | } 31 | applyStyle().catch(print); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.commondata/hyprlanddata.js: -------------------------------------------------------------------------------- 1 | const { Gdk } = imports.gi; 2 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 3 | const { exec } = Utils; 4 | 5 | export let monitors; 6 | 7 | // Mixes with Gdk monitor size cuz it reports monitor size scaled 8 | async function updateStuff() { 9 | monitors = JSON.parse(exec('hyprctl monitors -j')) 10 | const display = Gdk.Display.get_default(); 11 | monitors.forEach((monitor, i) => { 12 | const gdkMonitor = display.get_monitor(i); 13 | monitor.realWidth = monitor.width; 14 | monitor.realHeight = monitor.height; 15 | if (userOptions.monitors.scaleMethod.toLowerCase == "gdk") { 16 | monitor.width = gdkMonitor.get_geometry().width; 17 | monitor.height = gdkMonitor.get_geometry().height; 18 | } 19 | else { // == "division" 20 | monitor.width = Math.ceil(monitor.realWidth / monitor.scale); 21 | monitor.height = Math.ceil(monitor.realHeight / monitor.scale); 22 | } 23 | }); 24 | } 25 | 26 | updateStuff().catch(print); 27 | 28 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.commondata/quotes.js: -------------------------------------------------------------------------------- 1 | export const quotes = [ 2 | { 3 | quote: 'Nvidia, fuck you', 4 | author: 'Linus Torvalds', 5 | }, 6 | { 7 | quote: 'reproducible system? cock and vagina?', 8 | author: 'vaxry', 9 | }, 10 | { 11 | quote: "haha pointers hee hee i love pointe-\\\nProcess Vaxry exited with signal SIGSEGV", 12 | author: 'vaxry', 13 | } 14 | ]; 15 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.commondata/weather.js: -------------------------------------------------------------------------------- 1 | export const WWO_CODE = { 2 | "113": "Sunny", 3 | "116": "PartlyCloudy", 4 | "119": "Cloudy", 5 | "122": "VeryCloudy", 6 | "143": "Fog", 7 | "176": "LightShowers", 8 | "179": "LightSleetShowers", 9 | "182": "LightSleet", 10 | "185": "LightSleet", 11 | "200": "ThunderyShowers", 12 | "227": "LightSnow", 13 | "230": "HeavySnow", 14 | "248": "Fog", 15 | "260": "Fog", 16 | "263": "LightShowers", 17 | "266": "LightRain", 18 | "281": "LightSleet", 19 | "284": "LightSleet", 20 | "293": "LightRain", 21 | "296": "LightRain", 22 | "299": "HeavyShowers", 23 | "302": "HeavyRain", 24 | "305": "HeavyShowers", 25 | "308": "HeavyRain", 26 | "311": "LightSleet", 27 | "314": "LightSleet", 28 | "317": "LightSleet", 29 | "320": "LightSnow", 30 | "323": "LightSnowShowers", 31 | "326": "LightSnowShowers", 32 | "329": "HeavySnow", 33 | "332": "HeavySnow", 34 | "335": "HeavySnowShowers", 35 | "338": "HeavySnow", 36 | "350": "LightSleet", 37 | "353": "LightShowers", 38 | "356": "HeavyShowers", 39 | "359": "HeavyRain", 40 | "362": "LightSleetShowers", 41 | "365": "LightSleetShowers", 42 | "368": "LightSnowShowers", 43 | "371": "HeavySnowShowers", 44 | "374": "LightSleetShowers", 45 | "377": "LightSleet", 46 | "386": "ThunderyShowers", 47 | "389": "ThunderyHeavyRain", 48 | "392": "ThunderySnowShowers", 49 | "395": "HeavySnowShowers", 50 | } 51 | 52 | export const WEATHER_SYMBOL = { 53 | "Unknown": "air", 54 | "Cloudy": "cloud", 55 | "Fog": "foggy", 56 | "HeavyRain": "rainy", 57 | "HeavyShowers": "rainy", 58 | "HeavySnow": "snowing", 59 | "HeavySnowShowers": "snowing", 60 | "LightRain": "rainy", 61 | "LightShowers": "rainy", 62 | "LightSleet": "rainy", 63 | "LightSleetShowers": "rainy", 64 | "LightSnow": "cloudy_snowing", 65 | "LightSnowShowers": "cloudy_snowing", 66 | "PartlyCloudy": "partly_cloudy_day", 67 | "Sunny": "clear_day", 68 | "ThunderyHeavyRain": "thunderstorm", 69 | "ThunderyShowers": "thunderstorm", 70 | "ThunderySnowShowers": "thunderstorm", 71 | "VeryCloudy": "cloud", 72 | } 73 | 74 | export const NIGHT_WEATHER_SYMBOL = { 75 | "Unknown": "air", 76 | "Cloudy": "cloud", 77 | "Fog": "foggy", 78 | "HeavyRain": "rainy", 79 | "HeavyShowers": "rainy", 80 | "HeavySnow": "snowing", 81 | "HeavySnowShowers": "snowing", 82 | "LightRain": "rainy", 83 | "LightShowers": "rainy", 84 | "LightSleet": "rainy", 85 | "LightSleetShowers": "rainy", 86 | "LightSnow": "cloudy_snowing", 87 | "LightSnowShowers": "cloudy_snowing", 88 | "PartlyCloudy": "partly_cloudy_night", 89 | "Sunny": "clear_night", 90 | "ThunderyHeavyRain": "thunderstorm", 91 | "ThunderyShowers": "thunderstorm", 92 | "ThunderySnowShowers": "thunderstorm", 93 | "VeryCloudy": "cloud", 94 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/.commonwidgets/cairo_roundedcorner.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Gtk } = imports.gi; 3 | const Lang = imports.lang; 4 | 5 | export const RoundedCorner = (place, props) => Widget.DrawingArea({ 6 | ...props, 7 | hpack: place.includes('left') ? 'start' : 'end', 8 | vpack: place.includes('top') ? 'start' : 'end', 9 | setup: (widget) => Utils.timeout(1, () => { 10 | const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL); 11 | const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); 12 | widget.set_size_request(r, r); 13 | widget.connect('draw', Lang.bind(widget, (widget, cr) => { 14 | const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL); 15 | const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); 16 | // const borderColor = widget.get_style_context().get_property('color', Gtk.StateFlags.NORMAL); 17 | // const borderWidth = widget.get_style_context().get_border(Gtk.StateFlags.NORMAL).left; // ur going to write border-width: something anyway 18 | widget.set_size_request(r, r); 19 | 20 | switch (place) { 21 | case 'topright': 22 | cr.arc(r, r, r, Math.PI, 3 * Math.PI / 2); 23 | cr.lineTo(0, 0); 24 | break; 25 | 26 | case 'topleft': 27 | cr.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI); 28 | cr.lineTo(r, 0); 29 | break; 30 | 31 | case 'bottomleft': 32 | cr.arc(r, 0, r, Math.PI / 2, Math.PI); 33 | cr.lineTo(0, r); 34 | break; 35 | 36 | case 'bottomright': 37 | cr.arc(0, 0, r, 0, Math.PI / 2); 38 | cr.lineTo(r, r); 39 | break; 40 | } 41 | 42 | cr.closePath(); 43 | cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha); 44 | cr.fill(); 45 | // cr.setLineWidth(borderWidth); 46 | // cr.setSourceRGBA(borderColor.red, borderColor.green, borderColor.blue, borderColor.alpha); 47 | // cr.stroke(); 48 | })); 49 | }), 50 | }); -------------------------------------------------------------------------------- /src/share/sleex/modules/.commonwidgets/cairo_slider.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Gtk } = imports.gi; 3 | const Lang = imports.lang; 4 | 5 | export const AnimatedSlider = ({ 6 | className, 7 | value, 8 | ...rest 9 | }) => { 10 | return Widget.DrawingArea({ 11 | className: `${className}`, 12 | setup: (self) => { 13 | self.connect('draw', Lang.bind(self, (self, cr) => { 14 | const styleContext = self.get_style_context(); 15 | const allocatedWidth = self.get_allocated_width(); 16 | const allocatedHeight = self.get_allocated_height(); 17 | console.log(allocatedHeight, allocatedWidth) 18 | const minWidth = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); 19 | const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); 20 | const radius = styleContext.get_property('border-radius', Gtk.StateFlags.NORMAL); 21 | const bg = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL); 22 | const fg = styleContext.get_property('color', Gtk.StateFlags.NORMAL); 23 | const value = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 100; 24 | self.set_size_request(-1, minHeight); 25 | const width = allocatedHeight; 26 | const height = minHeight; 27 | 28 | cr.arc(radius, radius, radius, -1 * Math.PI, -0.5 * Math.PI); // Top-left 29 | cr.arc(width - radius, radius, radius, -0.5 * Math.PI, 0); // Top-right 30 | cr.arc(width - radius, height - radius, radius, 0, 0.5 * Math.PI); // Bottom-left 31 | cr.arc(radius, height - radius, radius, 0.5 * Math.PI, 1 * Math.PI); // Bottom-right 32 | cr.setSourceRGBA(bg.red, bg.green, bg.blue, bg.alpha); 33 | cr.closePath(); 34 | cr.fill(); 35 | 36 | // const valueWidth = width * value; 37 | // cr.arc(radius, radius, radius, -1 * Math.PI, -0.5 * Math.PI); // Top-left 38 | // cr.arc(valueWidth - radius, radius, radius, -0.5 * Math.PI, 0); // Top-right 39 | // cr.arc(valueWidth - radius, height - radius, radius, 0, 0.5 * Math.PI); // Bottom-left 40 | // cr.arc(radius, height - radius, radius, 0.5 * Math.PI, 1 * Math.PI); // Bottom-right 41 | // cr.setSourceRGBA(fg.red, fg.green, fg.blue, fg.alpha); 42 | // cr.closePath(); 43 | // cr.fill(); 44 | 45 | })); 46 | }, 47 | ...rest, 48 | }) 49 | } 50 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.commonwidgets/clickcloseregion.js: -------------------------------------------------------------------------------- 1 | import App from 'resource:///com/github/Aylur/ags/app.js'; 2 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 3 | import { monitors } from '../.commondata/hyprlanddata.js'; 4 | const { Box, EventBox } = Widget; 5 | 6 | export const clickCloseRegion = ({ name, multimonitor = true, monitor = 0, expand = true, fillMonitor = '' }) => { 7 | return EventBox({ 8 | child: Box({ 9 | expand: expand, 10 | css: ` 11 | min-width: ${fillMonitor.includes('h') ? monitors[monitor].width : 0}px; 12 | min-height: ${fillMonitor.includes('v') ? monitors[monitor].height : 0}px; 13 | `, 14 | }), 15 | setup: (self) => self.on('button-press-event', (self, event) => { // Any mouse button 16 | if (multimonitor) closeWindowOnAllMonitors(name); 17 | else App.closeWindow(name); 18 | }), 19 | }) 20 | } 21 | 22 | export default clickCloseRegion; 23 | 24 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.commonwidgets/materialicon.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | 3 | export const MaterialIcon = (icon, size, props = {}) => Widget.Label({ 4 | className: `icon-material txt-${size}`, 5 | label: icon, 6 | ...props, 7 | }) 8 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.commonwidgets/statusicons_languages.js: -------------------------------------------------------------------------------- 1 | // For keyboard layout in statusicons.js 2 | // This list is not exhaustive. It just includes known/possible languages of users of my dotfiles 3 | // Add your language here if you use multi-lang xkb input. Else, ignore 4 | // Note that something like "French (Canada)" should go before "French" 5 | // and "English (US)" should go before "English" 6 | export const languages = [ 7 | { 8 | layout: 'us', 9 | name: 'English (US)', 10 | flag: '🇺🇸' 11 | }, 12 | { 13 | layout: 'ru', 14 | name: 'Russian', 15 | flag: '🇷🇺', 16 | }, 17 | { 18 | layout: 'pl', 19 | name: 'Polish', 20 | flag: '🇷🇵🇵🇱', 21 | }, 22 | { 23 | layout: 'ro', 24 | name: 'Romanian', 25 | flag: '🇷🇴', 26 | }, 27 | { 28 | layout: 'ca', 29 | name: 'French (Canada)', 30 | flag: '🇫🇷', 31 | }, 32 | { 33 | layout: 'fr', 34 | name: 'French', 35 | flag: '🇫🇷', 36 | }, 37 | { 38 | layout: 'tr', 39 | name: 'Turkish', 40 | flag: '🇹🇷', 41 | }, 42 | { 43 | layout: 'jp', 44 | name: 'Japanese', 45 | flag: '🇯🇵', 46 | }, 47 | { 48 | layout: 'cn', 49 | name: 'Chinese', 50 | flag: '🇨🇳', 51 | }, 52 | { 53 | layout: 'vn', 54 | name: 'Vietnamese', 55 | flag: '🇻🇳', 56 | }, 57 | { 58 | layout: 'undef', 59 | name: 'Undefined', 60 | flag: '🧐', 61 | }, 62 | ] -------------------------------------------------------------------------------- /src/share/sleex/modules/.configuration/user_options.js: -------------------------------------------------------------------------------- 1 | const { GLib } = imports.gi; 2 | import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; 3 | import userOverrides from "../../user_options.js"; 4 | 5 | // Default options. 6 | const defaultConfigPath = `/usr/share/sleex/modules/.configuration/default_config.json`; 7 | let configOptions = {}; 8 | 9 | 10 | try { 11 | const defaultConfig = Utils.readFile(defaultConfigPath); 12 | configOptions = JSON.parse(defaultConfig); 13 | } catch (e) { 14 | console.error('Error loading user_options.default.json:', e); 15 | } 16 | 17 | // Override defaults with user's options 18 | let optionsOkay = true; 19 | function overrideConfigRecursive( 20 | userOverrides, 21 | configOptions = {}, 22 | check = true 23 | ) { 24 | for (const [key, value] of Object.entries(userOverrides)) { 25 | if (configOptions[key] === undefined && check) { 26 | optionsOkay = false; 27 | } else if (typeof value === "object" && !(value instanceof Array)) { 28 | if ( 29 | key === "substitutions" || 30 | key === "regexSubstitutions" || 31 | key === "extraGptModels" 32 | ) { 33 | overrideConfigRecursive(value, configOptions[key], false); 34 | } else overrideConfigRecursive(value, configOptions[key]); 35 | } else { 36 | configOptions[key] = value; 37 | } 38 | } 39 | } 40 | overrideConfigRecursive(userOverrides, configOptions); 41 | if (!optionsOkay) 42 | Utils.timeout(2000, () => 43 | Utils.execAsync([ 44 | "notify-send", 45 | "Update your user options", 46 | "One or more config options don't exist", 47 | "-a", 48 | "ags", 49 | ]).catch(print) 50 | ); 51 | 52 | globalThis["userOptions"] = configOptions; 53 | export default configOptions; 54 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.miscutils/files.js: -------------------------------------------------------------------------------- 1 | const { Gio, GLib } = imports.gi; 2 | 3 | export function fileExists(filePath) { 4 | let file = Gio.File.new_for_path(filePath); 5 | return file.query_exists(null); 6 | } 7 | 8 | export function expandTilde(path) { 9 | if (path.startsWith('~')) { 10 | return GLib.get_home_dir() + path.slice(1); 11 | } else { 12 | return path; 13 | } 14 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/.miscutils/icons.js: -------------------------------------------------------------------------------- 1 | const { Gtk } = imports.gi; 2 | 3 | export function iconExists(iconName) { 4 | let iconTheme = Gtk.IconTheme.get_default(); 5 | return iconTheme.has_icon(iconName); 6 | } 7 | 8 | export function substitute(str) { 9 | // Normal substitutions 10 | if (userOptions.icons.substitutions[str]) 11 | return userOptions.icons.substitutions[str]; 12 | 13 | // Regex substitutions 14 | for (let i = 0; i < userOptions.icons.regexSubstitutions.length; i++) { 15 | const substitution = userOptions.icons.regexSubstitutions[i]; 16 | const replacedName = str.replace( 17 | substitution.regex, 18 | substitution.replace, 19 | ); 20 | if (replacedName != str) return replacedName; 21 | } 22 | 23 | // Guess: convert to kebab case 24 | if (!iconExists(str)) str = str.toLowerCase().replace(/\s+/g, "-"); 25 | 26 | // Original string 27 | return str; 28 | } 29 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.miscutils/mathfuncs.js: -------------------------------------------------------------------------------- 1 | 2 | export function clamp(x, min, max) { 3 | return Math.min(Math.max(x, min), max); 4 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/.miscutils/md2pango.js: -------------------------------------------------------------------------------- 1 | // Converts from Markdown to Pango. This does not support code blocks. 2 | // For illogical-impulse, code blocks are treated separately, in their own GtkSourceView widgets. 3 | // Partly inherited from https://github.com/ubunatic/md2pango 4 | 5 | const monospaceFonts = 'JetBrains Mono NF, JetBrains Mono Nerd Font, JetBrains Mono NL, SpaceMono NF, SpaceMono Nerd Font, monospace'; 6 | 7 | const replacements = { 8 | 'indents': [ 9 | { name: 'BULLET', re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: ' $1- $3' }, 10 | { name: 'NUMBERING', re: /^(\s*[0-9]+\.\s)(.*)(\s*)$/, sub: ' $1 $2' }, 11 | ], 12 | 'escapes': [ 13 | { name: 'COMMENT', re: //, sub: '' }, 14 | { name: 'AMPERSTAND', re: /&/g, sub: '&' }, 15 | { name: 'LESSTHAN', re: //g, sub: '>' }, 17 | ], 18 | 'sections': [ 19 | { name: 'H1', re: /^(#\s+)(.*)(\s*)$/, sub: '$2' }, 20 | { name: 'H2', re: /^(##\s+)(.*)(\s*)$/, sub: '$2' }, 21 | { name: 'H3', re: /^(###\s+)(.*)(\s*)$/, sub: '$2' }, 22 | { name: 'H4', re: /^(####\s+)(.*)(\s*)$/, sub: '$2' }, 23 | { name: 'H5', re: /^(#####\s+)(.*)(\s*)$/, sub: '$2' }, 24 | ], 25 | 'styles': [ 26 | { name: 'BOLD', re: /(\*\*)(\S[\s\S]*?\S)(\*\*)/g, sub: "$2" }, 27 | { name: 'UND', re: /(__)(\S[\s\S]*?\S)(__)/g, sub: "$2" }, 28 | { name: 'EMPH', re: /\*(\S.*?\S)\*/g, sub: "$1" }, 29 | // { name: 'EMPH', re: /_(\S.*?\S)_/g, sub: "$1" }, 30 | { name: 'HEXCOLOR', re: /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g, sub: '#$1' }, 31 | { name: 'INLCODE', re: /(`)([^`]*)(`)/g, sub: '$2' }, 32 | // { name: 'UND', re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "$2" }, 33 | ], 34 | } 35 | 36 | const replaceCategory = (text, replaces) => { 37 | for (const type of replaces) { 38 | text = text.replace(type.re, type.sub); 39 | } 40 | return text; 41 | } 42 | 43 | // Main function 44 | 45 | export default (text) => { 46 | let lines = text.split('\n') 47 | let output = []; 48 | // Replace 49 | for (const line of lines) { 50 | let result = line; 51 | result = replaceCategory(result, replacements.indents); 52 | result = replaceCategory(result, replacements.escapes); 53 | result = replaceCategory(result, replacements.sections); 54 | result = replaceCategory(result, replacements.styles); 55 | output.push(result) 56 | } 57 | // Remove trailing whitespaces 58 | output = output.map(line => line.replace(/ +$/, '')) 59 | return output.join('\n'); 60 | } 61 | 62 | export const markdownTest = `## Inline formatting 63 | - **Bold** *Italics* __Underline__ 64 | - \`Monospace text\` 🤓 65 | - Colors 66 | - Nvidia green #7ABB08 67 | - Soundcloud orange #FF5500 68 | ## Code block 69 | \`\`\`cpp 70 | #include 71 | const std::string GREETING="UwU"; 72 | int main() { std::cout << GREETING; } 73 | \`\`\` 74 | ## LaTeX 75 | \`\`\`latex 76 | \\frac{d}{dx} \\left( \\frac{x-438}{x^2+23x-7} \\right) = \\frac{-x^2 + 869}{(x^2+23x-7)^2} \\\\ → \\\\ cos(2x) = 2cos^2(x) - 1 = 1 - 2sin^2(x) = cos^2(x) - sin^2(x) 77 | \`\`\` 78 | `; 79 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.miscutils/system.js: -------------------------------------------------------------------------------- 1 | const { GLib } = imports.gi; 2 | import Variable from 'resource:///com/github/Aylur/ags/variable.js'; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 4 | const { execAsync, exec } = Utils; 5 | 6 | export const distroID = exec(`bash -c 'cat /etc/os-release | grep "^ID=" | cut -d "=" -f 2 | sed "s/\\"//g"'`).trim(); 7 | export const isDebianDistro = (distroID == 'linuxmint' || distroID == 'ubuntu' || distroID == 'debian' || distroID == 'zorin' || distroID == 'popos' || distroID == 'raspbian' || distroID == 'kali'); 8 | export const isArchDistro = (distroID == 'arch' || distroID == 'endeavouros' || distroID == 'cachyos' || distroID == 'axos'); 9 | export const hasFlatpak = !!exec(`bash -c 'command -v flatpak'`); 10 | 11 | const LIGHTDARK_FILE_LOCATION = `${GLib.get_user_state_dir()}/ags/user/colormode.txt`; 12 | export const darkMode = Variable(!(Utils.readFile(LIGHTDARK_FILE_LOCATION).split('\n')[0].trim() == 'light')); 13 | darkMode.connect('changed', ({ value }) => { 14 | let lightdark = value ? "dark" : "light"; 15 | execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_state_dir()}/ags/user && sed -i "1s/.*/${lightdark}/" ${GLib.get_user_state_dir()}/ags/user/colormode.txt`]) 16 | .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`])) 17 | .then(execAsync(['bash', '-c', `command -v darkman && darkman set ${lightdark}`])) // Optional darkman integration 18 | .catch(print); 19 | }); 20 | globalThis['darkMode'] = darkMode; 21 | export const hasPlasmaIntegration = !!Utils.exec('bash -c "command -v plasma-browser-integration-host"'); 22 | 23 | export const getDistroIcon = () => { 24 | // Arches 25 | if(distroID == 'arch') return 'arch-symbolic'; 26 | if(distroID == 'endeavouros') return 'endeavouros-symbolic'; 27 | if(distroID == 'cachyos') return 'cachyos-symbolic'; 28 | // Funny flake 29 | if(distroID == 'nixos') return 'nixos-symbolic'; 30 | // Cool thing 31 | if(distroID == 'axos') return 'axos-symbolic'; 32 | // Debians 33 | if(distroID == 'fedora') return 'fedora-symbolic'; 34 | if(distroID == 'linuxmint') return 'ubuntu-symbolic'; 35 | if(distroID == 'ubuntu') return 'ubuntu-symbolic'; 36 | if(distroID == 'debian') return 'debian-symbolic'; 37 | if(distroID == 'zorin') return 'ubuntu-symbolic'; 38 | if(distroID == 'popos') return 'ubuntu-symbolic'; 39 | if(distroID == 'raspbian') return 'debian-symbolic'; 40 | if(distroID == 'kali') return 'debian-symbolic'; 41 | 42 | return 'linux-symbolic'; 43 | } 44 | 45 | export const getDistroName = () => { 46 | // Arches 47 | if(distroID == 'arch') return 'Arch Linux'; 48 | if(distroID == 'endeavouros') return 'EndeavourOS'; 49 | if(distroID == 'cachyos') return 'CachyOS'; 50 | // Funny flake 51 | if(distroID == 'nixos') return 'NixOS'; 52 | // Cool thing 53 | if(distroID == 'fedora') return 'Fedora'; 54 | if(distroID == 'axos') return 'AxOS'; 55 | // Debians 56 | if(distroID == 'linuxmint') return 'Linux Mint'; 57 | if(distroID == 'ubuntu') return 'Ubuntu'; 58 | if(distroID == 'debian') return 'Debian'; 59 | if(distroID == 'zorin') return 'Zorin'; 60 | if(distroID == 'popos') return 'Pop!_OS';4 61 | if(distroID == 'raspbian') return 'Raspbian'; 62 | if(distroID == 'kali') return 'Kali Linux'; 63 | 64 | return 'Linux'; 65 | } 66 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.widgethacks/advancedrevealers.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | 3 | const { Revealer, Scrollable } = Widget; 4 | 5 | export const MarginRevealer = ({ 6 | transition = 'slide_down', 7 | child, 8 | revealChild, 9 | showClass = 'element-show', // These are for animation curve, they don't really hide 10 | hideClass = 'element-hide', // Don't put margins in these classes! 11 | extraSetup = () => { }, 12 | ...rest 13 | }) => { 14 | const widget = Scrollable({ 15 | ...rest, 16 | attribute: { 17 | 'revealChild': true, // It'll be set to false after init if it's supposed to hide 18 | 'transition': transition, 19 | 'show': () => { 20 | if (widget.attribute.revealChild) return; 21 | widget.hscroll = 'never'; 22 | widget.vscroll = 'never'; 23 | child.toggleClassName(hideClass, false); 24 | child.toggleClassName(showClass, true); 25 | widget.attribute.revealChild = true; 26 | child.css = 'margin: 0px;'; 27 | }, 28 | 'hide': () => { 29 | if (!widget.attribute.revealChild) return; 30 | child.toggleClassName(hideClass, true); 31 | child.toggleClassName(showClass, false); 32 | widget.attribute.revealChild = false; 33 | if (widget.attribute.transition == 'slide_left') 34 | child.css = `margin-right: -${child.get_allocated_width()}px;`; 35 | else if (widget.attribute.transition == 'slide_right') 36 | child.css = `margin-left: -${child.get_allocated_width()}px;`; 37 | else if (widget.attribute.transition == 'slide_up') 38 | child.css = `margin-bottom: -${child.get_allocated_height()}px;`; 39 | else if (widget.attribute.transition == 'slide_down') 40 | child.css = `margin-top: -${child.get_allocated_height()}px;`; 41 | }, 42 | 'toggle': () => { 43 | if (widget.attribute.revealChild) widget.attribute.hide(); 44 | else widget.attribute.show(); 45 | }, 46 | }, 47 | child: child, 48 | hscroll: `${revealChild ? 'never' : 'always'}`, 49 | vscroll: `${revealChild ? 'never' : 'always'}`, 50 | setup: (self) => { 51 | extraSetup(self); 52 | } 53 | }); 54 | child.toggleClassName(`${revealChild ? showClass : hideClass}`, true); 55 | return widget; 56 | } 57 | 58 | // Allow reveal update by setting initial state and adding update method 59 | MarginRevealer.updateReveal = (widget, shouldReveal) => { 60 | if (shouldReveal) widget.attribute.show(); 61 | else widget.attribute.hide(); 62 | }; 63 | export const DoubleRevealer = ({ 64 | transition1 = 'slide_right', 65 | transition2 = 'slide_left', 66 | duration1 = 150, 67 | duration2 = 150, 68 | child, 69 | revealChild, 70 | ...rest 71 | }) => { 72 | const r2 = Revealer({ 73 | transition: transition2, 74 | transitionDuration: duration2, 75 | revealChild: revealChild, 76 | child: child, 77 | }); 78 | const r1 = Revealer({ 79 | transition: transition1, 80 | transitionDuration: duration1, 81 | revealChild: revealChild, 82 | child: r2, 83 | ...rest, 84 | }) 85 | r1.toggleRevealChild = (value) => { 86 | r1.revealChild = value; 87 | r2.revealChild = value; 88 | } 89 | return r1; 90 | } 91 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.widgethacks/popupwindow.js: -------------------------------------------------------------------------------- 1 | import App from 'resource:///com/github/Aylur/ags/app.js'; 2 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 3 | const { Box, Window } = Widget; 4 | 5 | 6 | export default ({ 7 | name, 8 | child, 9 | showClassName = "", 10 | hideClassName = "", 11 | ...props 12 | }) => { 13 | return Window({ 14 | name, 15 | visible: false, 16 | layer: 'top', 17 | ...props, 18 | 19 | child: Box({ 20 | setup: (self) => { 21 | self.keybind("Escape", () => closeEverything()); 22 | if (showClassName != "" && hideClassName !== "") { 23 | self.hook(App, (self, currentName, visible) => { 24 | if (currentName === name) { 25 | self.toggleClassName(hideClassName, !visible); 26 | } 27 | }); 28 | 29 | if (showClassName !== "" && hideClassName !== "") 30 | self.className = `${showClassName} ${hideClassName}`; 31 | } 32 | }, 33 | child: child, 34 | }), 35 | }); 36 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/.widgetutils/clickthrough.js: -------------------------------------------------------------------------------- 1 | import Cairo from 'gi://cairo?version=1.0'; 2 | 3 | export const dummyRegion = new Cairo.Region(); 4 | export const enableClickthrough = (self) => self.input_shape_combine_region(dummyRegion); -------------------------------------------------------------------------------- /src/share/sleex/modules/.widgetutils/cursorhover.js: -------------------------------------------------------------------------------- 1 | const { Gdk } = imports.gi; 2 | 3 | export function setupCursorHover(button) { // Hand pointing cursor on hover 4 | const display = Gdk.Display.get_default(); 5 | button.connect('enter-notify-event', () => { 6 | const cursor = Gdk.Cursor.new_from_name(display, 'pointer'); 7 | button.get_window().set_cursor(cursor); 8 | }); 9 | 10 | button.connect('leave-notify-event', () => { 11 | const cursor = Gdk.Cursor.new_from_name(display, 'default'); 12 | button.get_window().set_cursor(cursor); 13 | }); 14 | 15 | } 16 | 17 | export function setupCursorHoverGrab(button) { // Hand ready to grab on hover 18 | button.connect('enter-notify-event', () => { 19 | const display = Gdk.Display.get_default(); 20 | const cursor = Gdk.Cursor.new_from_name(display, 'grab'); 21 | button.get_window().set_cursor(cursor); 22 | }); 23 | 24 | button.connect('leave-notify-event', () => { 25 | const display = Gdk.Display.get_default(); 26 | const cursor = Gdk.Cursor.new_from_name(display, 'default'); 27 | button.get_window().set_cursor(cursor); 28 | }); 29 | } 30 | 31 | export function setupCursorHoverInfo(button) { // "?" mark cursor on hover 32 | const display = Gdk.Display.get_default(); 33 | button.connect('enter-notify-event', () => { 34 | const cursor = Gdk.Cursor.new_from_name(display, 'help'); 35 | button.get_window().set_cursor(cursor); 36 | }); 37 | 38 | button.connect('leave-notify-event', () => { 39 | const cursor = Gdk.Cursor.new_from_name(display, 'default'); 40 | button.get_window().set_cursor(cursor); 41 | }); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/share/sleex/modules/.widgetutils/keybind.js: -------------------------------------------------------------------------------- 1 | const { Gdk } = imports.gi; 2 | 3 | const MODS = { 4 | 'Shift': Gdk.ModifierType.SHIFT_MASK, 5 | 'Ctrl': Gdk.ModifierType.CONTROL_MASK, 6 | 'Alt': Gdk.ModifierType.ALT_MASK, 7 | 'Hyper': Gdk.ModifierType.HYPER_MASK, 8 | 'Meta': Gdk.ModifierType.META_MASK 9 | } 10 | 11 | export const checkKeybind = (event, keybind) => { 12 | const pressedModMask = event.get_state()[1]; 13 | const pressedKey = event.get_keyval()[1]; 14 | const keys = keybind.split('+'); 15 | for (let i = 0; i < keys.length; i++) { 16 | if (keys[i] in MODS) { 17 | if (!(pressedModMask & MODS[keys[i]])) { 18 | return false; 19 | } 20 | } else if (pressedKey !== Gdk[`KEY_${keys[i]}`]) { 21 | return false; 22 | } 23 | } 24 | return true; 25 | } 26 | -------------------------------------------------------------------------------- /src/share/sleex/modules/bar/normal/system.js: -------------------------------------------------------------------------------- 1 | // This is for the right pills of the bar. 2 | import Widget from "resource:///com/github/Aylur/ags/widget.js"; 3 | import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; 4 | const { execAsync } = Utils; 5 | const { GLib } = imports.gi; 6 | import { RoundedCorner } from "../../.commonwidgets/cairo_roundedcorner.js"; 7 | 8 | const time = Variable("", { 9 | poll: [ 10 | userOptions.time.interval, 11 | () => GLib.DateTime.new_now_local().format(userOptions.time.format), 12 | ], 13 | }); 14 | 15 | const date = Variable("", { 16 | poll: [ 17 | userOptions.time.dateInterval, 18 | () => GLib.DateTime.new_now_local().format(userOptions.time.dateFormatLong), 19 | ], 20 | }); 21 | 22 | const showTimeDate = () => { 23 | const TIMEDATE_FILE_LOCATION = `${GLib.get_user_state_dir()}/ags/user/show_timedate.txt`; 24 | const actual_show_timedate = Utils.exec(`bash -c "cat ${TIMEDATE_FILE_LOCATION}"`); 25 | actual_show_timedate == null ? actual_show_timedate = userOptions.appearance.showTimeDate : actual_show_timedate; 26 | return actual_show_timedate == 'true' ? true : false; 27 | } 28 | const BarClock = () => { 29 | if (!showTimeDate()) return null; 30 | else return Widget.Box({ 31 | vpack: "center", 32 | className: "spacing-h-4 bar-clock-box", 33 | children: [ 34 | Widget.Label({ 35 | className: "bar-time", 36 | label: time.bind(), 37 | }), 38 | Widget.Label({ 39 | className: "txt-norm txt-onLayer1", 40 | label: "•", 41 | }), 42 | Widget.Label({ 43 | className: "txt-smallie bar-date", 44 | label: date.bind(), 45 | }), 46 | ], 47 | }); 48 | }; 49 | 50 | const BarGroup = ({ child }) => 51 | Widget.Box({ 52 | className: "bar-group-margin bar-sides", 53 | children: [ 54 | Widget.Box({ 55 | className: "bar-group bar-group-standalone bar-group-pad-system bar-group-right", 56 | children: [child], 57 | }), 58 | ], 59 | }); 60 | 61 | const switchToRelativeWorkspace = async (self, num) => { 62 | try { 63 | const Hyprland = ( 64 | await import("resource:///com/github/Aylur/ags/service/hyprland.js") 65 | ).default; 66 | Hyprland.messageAsync( 67 | `dispatch workspace ${num > 0 ? "+" : ""}${num}` 68 | ).catch(print); 69 | } catch { 70 | execAsync([ 71 | `${App.configDir}/scripts/sway/swayToRelativeWs.sh`, 72 | `${num}`, 73 | ]).catch(print); 74 | } 75 | }; 76 | 77 | export default () => 78 | !showTimeDate() ? Widget.Box({}) : Widget.EventBox({ 79 | onScrollUp: (self) => switchToRelativeWorkspace(self, -1), 80 | onScrollDown: (self) => switchToRelativeWorkspace(self, +1), 81 | onPrimaryClick: () => App.toggleWindow("dashboard"), 82 | child: Widget.Box({ 83 | children: [ 84 | // BarCornerBottomright(), 85 | BarGroup({ child: BarClock() }), 86 | // BarCornerTopright(), 87 | ], 88 | }), 89 | }); 90 | 91 | // const BarCornerBottomright = () => Widget.Box({ 92 | // child: RoundedCorner('bottomright', { className: 'corner', }), 93 | // }); 94 | // const BarCornerTopright = () => Widget.Box({ 95 | // child: RoundedCorner('topright', { className: 'corner', }), 96 | // }); -------------------------------------------------------------------------------- /src/share/sleex/modules/bar/normal/tray.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js'; 3 | const { Box, Icon, Button } = Widget; 4 | const { Gravity } = imports.gi.Gdk; 5 | 6 | const SysTrayItem = (item) => item.id !== null ? Button({ 7 | className: 'bar-systray-item', 8 | child: Icon({ hpack: 'center' }).bind('icon', item, 'icon'), 9 | setup: (self) => self 10 | .hook(item, (self) => self.tooltipMarkup = item['tooltip-markup']) 11 | , 12 | onPrimaryClick: (_, event) => item.activate(event), 13 | onSecondaryClick: (btn, event) => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), 14 | }) : null; 15 | 16 | export const Tray = (props = {}) => { 17 | const trayContent = Box({ 18 | className: 'margin-right-5 spacing-h-15', 19 | setup: (self) => self 20 | .hook(SystemTray, (self) => { 21 | self.children = SystemTray.items.map(SysTrayItem); 22 | self.show_all(); 23 | }) 24 | , 25 | }); 26 | const trayRevealer = Widget.Revealer({ 27 | revealChild: true, 28 | transition: 'slide_left', 29 | transitionDuration: userOptions.animations.durationLarge, 30 | child: trayContent, 31 | }); 32 | return Box({ 33 | ...props, 34 | children: [trayRevealer], 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /src/share/sleex/modules/bar/normal/workspaces_box.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | 3 | export default () => { 4 | return Widget.box({ 5 | name: `workspace-corner`, 6 | exclusivity: 'ignore', 7 | visible: true, 8 | }); 9 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/cheatsheet/periodictable.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | import { niceTypes, periodicTable, series } from "./data_periodictable.js"; 3 | const { Box, Icon, Label } = Widget; 4 | 5 | export default () => { 6 | const ElementTile = (element) => { 7 | return Box({ 8 | vertical: true, 9 | tooltipText: element.electronConfig ? `${element.electronConfig}` : null, 10 | className: `cheatsheet-periodictable-${element.type}`, 11 | children: element.name == '' ? null : [ 12 | Box({ 13 | className: 'padding-left-8 padding-right-8 padding-top-8', 14 | children: [ 15 | Label({ 16 | label: `${element.number}`, 17 | className: "cheatsheet-periodictable-elementnum txt-tiny txt-bold", 18 | }), 19 | Box({ hexpand: true }), 20 | Label({ 21 | label: `${element.weight}`, 22 | className: "txt-smaller", 23 | }) 24 | ] 25 | }), 26 | element.icon ? Icon({ 27 | icon: element.icon, 28 | className: "txt-hugerass txt-bold", 29 | }) : Label({ 30 | label: `${element.symbol}`, 31 | className: "cheatsheet-periodictable-elementsymbol", 32 | }), 33 | Label({ 34 | label: `${element.name}`, 35 | className: "txt-tiny", 36 | }) 37 | ] 38 | }) 39 | } 40 | const BoardColor = (type) => Box({ 41 | className: 'spacing-h-5', 42 | children: [ 43 | Box({ 44 | homogeneous: true, 45 | className: `cheatsheet-periodictable-legend-color-wrapper`, 46 | children: [Box({ 47 | className: `cheatsheet-periodictable-legend-color-${type}`, 48 | })] 49 | }), 50 | Label({ 51 | label: `${niceTypes[type]}`, 52 | className: "txt txt-small", 53 | }) 54 | ] 55 | }) 56 | const mainBoard = Box({ 57 | hpack: 'center', 58 | vertical: true, 59 | className: "spacing-v-3", 60 | children: periodicTable.map((row, _) => Box({ // Rows 61 | className: "spacing-h-5", 62 | children: row.map((element, _) => ElementTile(element)) 63 | })), 64 | }); 65 | const seriesBoard = Box({ 66 | hpack: 'center', 67 | vertical: true, 68 | className: "spacing-v-3", 69 | children: series.map((row, _) => Box({ // Rows 70 | className: "spacing-h-5", 71 | children: row.map((element, _) => ElementTile(element)) 72 | })), 73 | }); 74 | const legend = Box({ 75 | hpack: 'center', 76 | className: 'spacing-h-20', 77 | children: [ 78 | BoardColor('metal'), 79 | BoardColor('nonmetal'), 80 | BoardColor('noblegas'), 81 | BoardColor('lanthanum'), 82 | BoardColor('actinium'), 83 | ] 84 | }) 85 | return Box({ 86 | vertical: true, 87 | className: 'spacing-v-20', 88 | children: [ 89 | mainBoard, 90 | seriesBoard, 91 | legend 92 | ] 93 | }) 94 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/calendar_layout.js: -------------------------------------------------------------------------------- 1 | function checkLeapYear(year) { 2 | return ( 3 | year % 400 == 0 || 4 | (year % 4 == 0 && year % 100 != 0)); 5 | } 6 | 7 | function getMonthDays(month, year) { 8 | const leapYear = checkLeapYear(year); 9 | if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 31; 10 | if (month == 2 && leapYear) return 29; 11 | if (month == 2 && !leapYear) return 28; 12 | return 30; 13 | } 14 | 15 | function getNextMonthDays(month, year) { 16 | const leapYear = checkLeapYear(year); 17 | if (month == 1 && leapYear) return 29; 18 | if (month == 1 && !leapYear) return 28; 19 | if (month == 12) return 31; 20 | if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30; 21 | return 31; 22 | } 23 | 24 | function getPrevMonthDays(month, year) { 25 | const leapYear = checkLeapYear(year); 26 | if (month == 3 && leapYear) return 29; 27 | if (month == 3 && !leapYear) return 28; 28 | if (month == 1) return 31; 29 | if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30; 30 | return 31; 31 | } 32 | 33 | export function getCalendarLayout(dateObject, highlight) { 34 | if (!dateObject) dateObject = new Date(); 35 | const weekday = (dateObject.getDay() + 6) % 7; // MONDAY IS THE FIRST DAY OF THE WEEK 36 | const day = dateObject.getDate(); 37 | const month = dateObject.getMonth() + 1; 38 | const year = dateObject.getFullYear(); 39 | const weekdayOfMonthFirst = (weekday + 35 - (day - 1)) % 7; 40 | const daysInMonth = getMonthDays(month, year); 41 | const daysInNextMonth = getNextMonthDays(month, year); 42 | const daysInPrevMonth = getPrevMonthDays(month, year); 43 | 44 | // Fill 45 | var monthDiff = (weekdayOfMonthFirst == 0 ? 0 : -1); 46 | var toFill, dim; 47 | if(weekdayOfMonthFirst == 0) { 48 | toFill = 1; 49 | dim = daysInMonth; 50 | } 51 | else { 52 | toFill = (daysInPrevMonth - (weekdayOfMonthFirst - 1)); 53 | dim = daysInPrevMonth; 54 | } 55 | var calendar = [...Array(6)].map(() => Array(7)); 56 | var i = 0, j = 0; 57 | while (i < 6 && j < 7) { 58 | calendar[i][j] = { 59 | "day": toFill, 60 | "today": ((toFill == day && monthDiff == 0 && highlight) ? 1 : ( 61 | monthDiff == 0 ? 0 : 62 | -1 63 | )) 64 | }; 65 | // Increment 66 | toFill++; 67 | if (toFill > dim) { // Next month? 68 | monthDiff++; 69 | if (monthDiff == 0) 70 | dim = daysInMonth; 71 | else if (monthDiff == 1) 72 | dim = daysInNextMonth; 73 | toFill = 1; 74 | } 75 | // Next tile 76 | j++; 77 | if (j == 7) { 78 | j = 0; 79 | i++; 80 | } 81 | 82 | } 83 | return calendar; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/main.js: -------------------------------------------------------------------------------- 1 | import PopupWindow from '../.widgethacks/popupwindow.js'; 2 | import SidebarRight from "./dashboard.js"; 3 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 4 | const { Box } = Widget; 5 | import clickCloseRegion from '../.commonwidgets/clickcloseregion.js'; 6 | 7 | export default () => PopupWindow({ 8 | keymode: 'on-demand', 9 | name: 'dashboard', 10 | child: Box({ 11 | children: [ 12 | clickCloseRegion({ name: 'dashboard', multimonitor: false }), 13 | SidebarRight(), 14 | ] 15 | }) 16 | }); 17 | -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/name.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 3 | import { setupCursorHover } from '../.widgetutils/cursorhover.js'; 4 | const { execAsync } = Utils; 5 | const { Box, Button, Icon, Label } = Widget; 6 | 7 | export default () => Box({ 8 | className: 'name techfont', 9 | children: [ 10 | Label({ 11 | label: 'Sleex' 12 | }), 13 | Box({ hexpand: true }), 14 | Button({ 15 | className: 'sidebar-module-btn-arrow', 16 | onClicked: () => execAsync(['xdg-open', 'https://github.com/axos-project/sleex']).catch(print), 17 | child: Icon({ 18 | className: 'txt txt-norm', 19 | icon: 'github-symbolic', 20 | }), 21 | setup: setupCursorHover, 22 | }) 23 | ] 24 | }) 25 | -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/quote.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' 4 | 5 | const MakeRequest = async () => { 6 | try { 7 | const response = await Utils.fetch("https://quotes-api-self.vercel.app/quote"); 8 | const data = await response.json(); 9 | return { 10 | quote: data.quote, 11 | author: data.author 12 | }; 13 | } catch (error) { 14 | console.error('Error fetching quote:', error); 15 | return { 16 | quote: 'Unable to fetch quote', 17 | author: 'Unknown' 18 | }; 19 | } 20 | }; 21 | 22 | export const QuoteWidget = () => { 23 | const quoteLabel = Label({ 24 | wrap: true, 25 | className: 'txt txt-quote', 26 | label: 'Loading...' 27 | }); 28 | 29 | const authorLabel = Label({ 30 | className: 'txt txt-small', 31 | label: 'Loading...' 32 | }); 33 | 34 | // Immediately invoke async function to update labels 35 | (async () => { 36 | const { quote, author } = await MakeRequest(); 37 | quoteLabel.label = quote; 38 | authorLabel.label = author; 39 | // console.log('Quote:', quote); 40 | // console.log('Author:', author); 41 | })(); 42 | 43 | return Box({ 44 | vertical: true, 45 | className: 'spacing-v-5 quote-box', 46 | children: [ 47 | quoteLabel, 48 | authorLabel 49 | ] 50 | }) 51 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/tabs/home.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box } = Widget; 3 | import { userWidget } from '../widgets/user_widget.js'; 4 | import { clockWidget } from '../widgets/clock.js'; 5 | import { QuoteWidget } from '../widgets/quote.js'; 6 | import { MusicWidget } from '../widgets/music.js'; 7 | import { WeatherWidget } from '../widgets/weather.js'; 8 | import { githubWidget } from '../widgets/github.js'; 9 | import { ModuleCalendar } from "../widgets/calendar.js"; 10 | import ModuleNotificationList from "../centermodules/notificationlist.js"; 11 | 12 | 13 | export default () => Box({ 14 | vertical: true, 15 | children: [ 16 | Box({ 17 | children: [ 18 | Box({ 19 | vertical: true, 20 | children: [ 21 | userWidget(), 22 | clockWidget(), 23 | githubWidget() 24 | ] 25 | }), 26 | Box({ 27 | vertical: true, 28 | children: [ 29 | Box({ 30 | children: [ 31 | Box({ 32 | vertical: true, 33 | children: [ 34 | ModuleNotificationList(), 35 | ] 36 | }), 37 | Box({ 38 | vertical: true, 39 | children: [ 40 | MusicWidget(), 41 | WeatherWidget(), 42 | ModuleCalendar(), 43 | ] 44 | }) 45 | ] 46 | }), 47 | ] 48 | }) 49 | 50 | ] 51 | }), 52 | QuoteWidget() 53 | ] 54 | }); -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/tabs/settings.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box } = Widget; 3 | import ModuleAudioControls from "../centermodules/audiocontrols.js"; 4 | import ModuleWifiNetworks from "../centermodules/wifinetworks.js"; 5 | import ModuleBluetooth from "../centermodules/bluetooth.js"; 6 | import ModuleConfigure from "../centermodules/configure.js"; 7 | 8 | 9 | export default () => Box({ 10 | children: [ 11 | ModuleConfigure(), 12 | Box({ 13 | vexpand: true, 14 | vertical: true, 15 | className: 'spacing-v-15', 16 | children: [ 17 | ModuleBluetooth(), 18 | ModuleAudioControls() 19 | ] 20 | }), 21 | ModuleWifiNetworks(), 22 | ] 23 | }); -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/tabs/todo.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | import { TodoWidget } from "../widgets/todolist.js"; 4 | import { todoTabs } from '../widgets/todo_tag.js'; 5 | import { UndoneTodoList } from '../widgets/todolist.js'; 6 | import { todoItems } from '../widgets/todolist.js'; 7 | 8 | export default () => Box({ 9 | children: [ 10 | UndoneTodoList(), 11 | todoItems(true), 12 | ] 13 | }) -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/calendar_layout.js: -------------------------------------------------------------------------------- 1 | function checkLeapYear(year) { 2 | return ( 3 | year % 400 == 0 || 4 | (year % 4 == 0 && year % 100 != 0)); 5 | } 6 | 7 | function getMonthDays(month, year) { 8 | const leapYear = checkLeapYear(year); 9 | if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 31; 10 | if (month == 2 && leapYear) return 29; 11 | if (month == 2 && !leapYear) return 28; 12 | return 30; 13 | } 14 | 15 | function getNextMonthDays(month, year) { 16 | const leapYear = checkLeapYear(year); 17 | if (month == 1 && leapYear) return 29; 18 | if (month == 1 && !leapYear) return 28; 19 | if (month == 12) return 31; 20 | if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30; 21 | return 31; 22 | } 23 | 24 | function getPrevMonthDays(month, year) { 25 | const leapYear = checkLeapYear(year); 26 | if (month == 3 && leapYear) return 29; 27 | if (month == 3 && !leapYear) return 28; 28 | if (month == 1) return 31; 29 | if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30; 30 | return 31; 31 | } 32 | 33 | export function getCalendarLayout(dateObject, highlight) { 34 | if (!dateObject) dateObject = new Date(); 35 | const weekday = (dateObject.getDay() + 6) % 7; // MONDAY IS THE FIRST DAY OF THE WEEK 36 | const day = dateObject.getDate(); 37 | const month = dateObject.getMonth() + 1; 38 | const year = dateObject.getFullYear(); 39 | const weekdayOfMonthFirst = (weekday + 35 - (day - 1)) % 7; 40 | const daysInMonth = getMonthDays(month, year); 41 | const daysInNextMonth = getNextMonthDays(month, year); 42 | const daysInPrevMonth = getPrevMonthDays(month, year); 43 | 44 | // Fill 45 | var monthDiff = (weekdayOfMonthFirst == 0 ? 0 : -1); 46 | var toFill, dim; 47 | if(weekdayOfMonthFirst == 0) { 48 | toFill = 1; 49 | dim = daysInMonth; 50 | } 51 | else { 52 | toFill = (daysInPrevMonth - (weekdayOfMonthFirst - 1)); 53 | dim = daysInPrevMonth; 54 | } 55 | var calendar = [...Array(6)].map(() => Array(7)); 56 | var i = 0, j = 0; 57 | while (i < 6 && j < 7) { 58 | calendar[i][j] = { 59 | "day": toFill, 60 | "today": ((toFill == day && monthDiff == 0 && highlight) ? 1 : ( 61 | monthDiff == 0 ? 0 : 62 | -1 63 | )) 64 | }; 65 | // Increment 66 | toFill++; 67 | if (toFill > dim) { // Next month? 68 | monthDiff++; 69 | if (monthDiff == 0) 70 | dim = daysInMonth; 71 | else if (monthDiff == 1) 72 | dim = daysInNextMonth; 73 | toFill = 1; 74 | } 75 | // Next tile 76 | j++; 77 | if (j == 7) { 78 | j = 0; 79 | i++; 80 | } 81 | 82 | } 83 | return calendar; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/clock.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { GLib } = imports.gi; 3 | 4 | export const clockWidget = () => { 5 | 6 | const time = Variable("", { 7 | poll: [ 8 | userOptions.time.interval, 9 | () => GLib.DateTime.new_now_local().format(userOptions.time.format), 10 | ], 11 | }); 12 | 13 | const rawDate = new Date(); 14 | const date = Variable("", { 15 | poll: [ 16 | userOptions.time.dateInterval, 17 | () => rawDate.toLocaleDateString([], { weekday: 'long', month: 'long', day: 'numeric' }), 18 | ], 19 | }); 20 | 21 | return Widget.Box({ 22 | vertical: true, 23 | className: 'clock-widget dash-widget spacing-v-5', 24 | children: [ 25 | Widget.Label({ 26 | className: 'txt txt-clock', 27 | hpack: 'center', 28 | label: time.bind(), 29 | }), 30 | Widget.Label({ 31 | className: 'txt txt-medium', 32 | hpack: 'center', 33 | label: date.bind(), 34 | }), 35 | ], 36 | }); 37 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/github.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' 4 | const { exec } = Utils; 5 | 6 | 7 | const request = async () => { 8 | try { 9 | const url = 'https://github-contributions.vercel.app/api/v1/levraiardox' 10 | const response = await Utils.fetch(url); 11 | const data = await response.json(); 12 | return { 13 | contributions: data.years[0].total 14 | } 15 | } catch (error) { 16 | console.error("Unable to fetch contributions: ", error) 17 | return { 18 | contributions: "error" 19 | } 20 | } 21 | } 22 | 23 | export const githubWidget = () => { 24 | const contribLabel = new Label({ 25 | className: 'txt txt-contrib', 26 | hpack: 'center', 27 | label: `Loading...`, 28 | }); 29 | 30 | (async () => { 31 | const { contributions } = await request(); 32 | contribLabel.label = `${contributions}`; 33 | })(); 34 | 35 | return new Box({ 36 | vertical: true, 37 | className: 'github-widget dash-widget spacing-v-5', 38 | children: [ 39 | contribLabel, 40 | new Label({ 41 | className: 'txt txt-medium', 42 | hpack: 'center', 43 | label: 'contributions this year', 44 | }), 45 | new Label({ 46 | className: 'txt txt-author', 47 | hpack: 'center', 48 | label: '@levraiardox' 49 | }) 50 | ], 51 | }); 52 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/name.js: -------------------------------------------------------------------------------- 1 | import Widget from "resource:///com/github/Aylur/ags/widget.js"; 2 | import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; 3 | import { setupCursorHover } from "../../.widgetutils/cursorhover.js"; 4 | const { execAsync } = Utils; 5 | const { Box, Button, Icon, Label } = Widget; 6 | 7 | export default () => 8 | Box({ 9 | className: "name techfont", 10 | children: [ 11 | Label({ 12 | label: "Sleex", 13 | }), 14 | Box({ hexpand: true }), 15 | Button({ 16 | className: "sidebar-module-btn-arrow", 17 | onClicked: () => 18 | execAsync([ 19 | "xdg-open", 20 | "https://github.com/axos-project/sleex", 21 | ]).catch(print), 22 | child: Icon({ 23 | className: "txt txt-norm", 24 | icon: "github-symbolic", 25 | }), 26 | setup: setupCursorHover, 27 | }), 28 | ], 29 | }); 30 | -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/quote.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' 4 | 5 | const MakeRequest = async () => { 6 | try { 7 | const response = await Utils.fetch("https://quotes-api-self.vercel.app/quote"); 8 | const data = await response.json(); 9 | return { 10 | quote: data.quote, 11 | author: data.author 12 | }; 13 | } catch (error) { 14 | console.error('Error fetching quote:', error); 15 | return { 16 | quote: 'Unable to fetch quote', 17 | author: 'Unknown' 18 | }; 19 | } 20 | }; 21 | 22 | export const QuoteWidget = () => { 23 | const quoteLabel = new Label({ 24 | wrap: true, 25 | hpack: 'center', 26 | className: 'txt txt-medium', 27 | label: 'Loading...' 28 | }); 29 | 30 | const authorLabel = new Label({ 31 | hpack: 'center', 32 | className: 'txt txt-small txt-bold txt-quote-author', 33 | label: 'Loading...' 34 | }); 35 | 36 | // Immediately invoke async function to update labels 37 | (async () => { 38 | const { quote, author } = await MakeRequest(); 39 | quoteLabel.label = quote; 40 | authorLabel.label = author; 41 | // console.log('Quote:', quote); 42 | // console.log('Author:', author); 43 | })(); 44 | 45 | return new Box({ 46 | vertical: true, 47 | className: 'spacing-v-5 dash-widget quote-widget', 48 | children: [ 49 | quoteLabel, 50 | authorLabel 51 | ] 52 | }) 53 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/timer.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | 4 | export const timerWidget = () => { 5 | return Box({ 6 | className: 'dash-widget timer-widget', 7 | vexpand: true, 8 | vertical: true, 9 | children: [ 10 | Label({ 11 | className: 'txt txt-small timer-title-label', 12 | label: "You've focused for" 13 | }), 14 | Label({ 15 | className: 'txt txt-large txt-clock', 16 | label: '3h 45m' 17 | }), 18 | Label({ 19 | className: 'txt txt-small timer-title-label', 20 | label: "today" 21 | }) 22 | ] 23 | }) 24 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/todo_tag.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | 4 | export const todoTabs = () => { 5 | return Box({ 6 | className: 'dash-widget', 7 | hexpand: true 8 | }) 9 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/dashboard/widgets/user_widget.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | const { Box, Label } = Widget; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' 4 | const { exec } = Utils; 5 | 6 | export const userWidget = () => { 7 | 8 | const userName = `${exec('whoami')}`; 9 | const userNameCapitalized = userName.charAt(0).toUpperCase() + userName.slice(1); 10 | 11 | const avatar = Widget.Box({ 12 | className: 'avatar-widget', 13 | css: ` 14 | background-image: url('file:///var/lib/AccountsService/icons/${userName}'); 15 | background-size: cover; 16 | background-position: center; 17 | `, 18 | }); 19 | 20 | return Widget.Box({ 21 | vexpand: true, 22 | vertical: true, 23 | className: 'user-widget dash-widget spacing-v-5', 24 | children: [ 25 | Widget.Box({ 26 | hexpand: false, 27 | hpack: 'center', 28 | child: avatar, 29 | }), 30 | Widget.Label({ 31 | className: 'txt txt-title', 32 | hpack: 'center', 33 | label: "Welcome back, " + userNameCapitalized, 34 | }), 35 | Widget.Label({ 36 | className: 'txt txt-medium', 37 | hpack: 'center', 38 | label: "Today is a good day to have a good day.", 39 | }), 40 | ], 41 | }); 42 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/desktopbackground/data_quicklaunches.js: -------------------------------------------------------------------------------- 1 | export const quickLaunchItems = [ 2 | { 3 | "name": "GitHub", 4 | "command": "xdg-open 'https://github.com/ $" 5 | }, 6 | { 7 | "name": "Terminal", 8 | "command": "foot &" 9 | }, 10 | { 11 | "name": "Discord", 12 | "command": "discord $" 13 | }, 14 | ] 15 | -------------------------------------------------------------------------------- /src/share/sleex/modules/desktopbackground/main.js: -------------------------------------------------------------------------------- 1 | import Widget from "resource:///com/github/Aylur/ags/widget.js"; 2 | 3 | import WallpaperImage from "./wallpaper.js"; 4 | import TimeAndLaunchesWidget from "./timeandlaunches.js"; 5 | import SystemWidget from "./system.js"; 6 | 7 | export default (monitor) => 8 | Widget.Window({ 9 | name: `desktopbackground${monitor}`, 10 | // anchor: ['top', 'bottom', 'left', 'right'], 11 | layer: "background", 12 | exclusivity: "ignore", 13 | visible: true, 14 | child: Widget.Overlay({ 15 | child: WallpaperImage(monitor), 16 | // child: Widget.Box({}), 17 | overlays: [TimeAndLaunchesWidget(), SystemWidget()], 18 | setup: (self) => { 19 | self.set_overlay_pass_through(self.get_children()[1], true); 20 | }, 21 | }), 22 | }); 23 | -------------------------------------------------------------------------------- /src/share/sleex/modules/desktopbackground/timeandlaunches.js: -------------------------------------------------------------------------------- 1 | const { GLib } = imports.gi; 2 | import Widget from "resource:///com/github/Aylur/ags/widget.js"; 3 | const { Box, Label, Overlay } = Widget; 4 | import { AnimatedCircProg } from "../.commonwidgets/cairo_circularprogress.js"; 5 | import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; 6 | const { exec } = Utils; 7 | 8 | const TimeAndDate = () => 9 | Box({ 10 | vertical: true, 11 | hpack: "center", 12 | className: "spacing-v-5", 13 | children: [ 14 | Label({ 15 | className: "bg-time-clock", 16 | label: GLib.DateTime.new_now_local().format(userOptions.time.format), 17 | setup: (self) => 18 | self.poll(userOptions.time.interval, (label) => { 19 | label.label = GLib.DateTime.new_now_local().format( 20 | userOptions.time.format 21 | ); 22 | }), 23 | }), 24 | Label({ 25 | className: "bg-time-date", 26 | hpack: "center", 27 | label: GLib.DateTime.new_now_local().format( 28 | userOptions.time.dateFormatLong 29 | ), 30 | setup: (self) => 31 | self.poll(userOptions.time.dateInterval, (label) => { 32 | label.label = GLib.DateTime.new_now_local().format( 33 | userOptions.time.dateFormatLong 34 | ); 35 | }), 36 | }), 37 | ], 38 | }); 39 | 40 | const analogClock = () => { 41 | const HourProgress = () => { 42 | const _updateProgress = (circprog) => { 43 | // Set circular progress value 44 | const hour = (exec("date '+%I'") / 12) * 100; 45 | circprog.css = `font-size: ${hour}px;`; 46 | }; 47 | return AnimatedCircProg({ 48 | className: "hours-circprog", 49 | vpack: "center", 50 | hpack: "center", 51 | extraSetup: (self) => self.poll(1000, _updateProgress), 52 | }); 53 | }; 54 | const MinuteProgress = () => { 55 | const _updateProgress = (circprog) => { 56 | // Set circular progress value 57 | const minute = (exec("date '+%M'") / 60) * 100; 58 | circprog.css = `font-size: ${minute}px;`; 59 | }; 60 | return AnimatedCircProg({ 61 | className: "minutes-circprog", 62 | vpack: "center", 63 | hpack: "center", 64 | extraSetup: (self) => self.poll(1000, _updateProgress), 65 | }); 66 | }; 67 | return Overlay({ 68 | child: Box({ 69 | vpack: "center", 70 | hpack: "center", 71 | child: HourProgress(), 72 | }), 73 | overlays: [MinuteProgress()], 74 | }); 75 | }; 76 | 77 | // const showAnalog = () => { 78 | // const ANALOGCLOCK_FILE_LOCATION = `${GLib.get_user_state_dir()}/ags/user/show_analogclock.txt`; 79 | // const show_analogclock = Utils.readFile(ANALOGCLOCK_FILE_LOCATION); 80 | // show_analogclock == null ? show_analogclock = userOptions.appearance.showAnalogClock : show_analogclock; 81 | // return show_analogclock == 'true' ? true : false; 82 | // } 83 | 84 | export default () => { 85 | // if (showAnalog()) return Box({ 86 | // hpack: "center", 87 | // vpack: "center", 88 | // vertical: true, 89 | // className: "bg-time-box", 90 | // children: [ 91 | // analogClock(), 92 | // ], 93 | // }); 94 | return Box({ 95 | hpack: "center", 96 | vpack: "center", 97 | vertical: true, 98 | className: "bg-time-box", 99 | children: [ 100 | TimeAndDate(), 101 | ], 102 | }); 103 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/indicators/indicatorvalueBrightness.js: -------------------------------------------------------------------------------- 1 | // This file is for brightness/volume indicators 2 | // noinspection JSFileReferences 3 | import Widget from "resource:///com/github/Aylur/ags/widget.js"; 4 | const { Box, Revealer } = Widget; 5 | import Brightness from "../../services/brightness.js"; 6 | import Indicator from "../../services/indicator.js"; 7 | import { OsdValue } from "./indicatorvalues.js"; 8 | import { RoundedCorner } from "../.commonwidgets/cairo_roundedcorner.js"; 9 | 10 | const BrightnessOsd = (monitor = 0) => { 11 | const brightnessIndicator = OsdValue({ 12 | icon: "light_mode", 13 | extraClassName: "osd-brightness", 14 | extraProgressClassName: "osd-brightness-progress", 15 | labelSetup: (self) => 16 | self.hook( 17 | Brightness[monitor], 18 | (self) => { 19 | self.label = `${Math.round( 20 | Brightness[monitor].screen_value * 100 21 | )}`; 22 | }, 23 | "notify::screen-value" 24 | ), 25 | progressSetup: (self) => 26 | self.hook( 27 | Brightness[monitor], 28 | (progress) => { 29 | const updateValue = Brightness[monitor].screen_value; 30 | if (updateValue !== progress.value) Indicator.popup(1); 31 | progress.value = updateValue; 32 | }, 33 | "notify::screen-value" 34 | ), 35 | }); 36 | 37 | return Revealer({ 38 | transition: "slide_down", 39 | transitionDuration: userOptions.animations.durationLarge, 40 | revealChild: false, 41 | setup: (self) => 42 | self.hook( 43 | Indicator, 44 | (revealer, value) => { 45 | if (value > -1) self.revealChild = true; 46 | else self.revealChild = false; 47 | }, 48 | "popup" 49 | ), 50 | child: Box({ 51 | hpack: "center", 52 | vertical: false, 53 | className: "spacing-h--10", 54 | children: [brightnessIndicator, RoundedCorner('topright', { className: 'corner'})], 55 | }), 56 | }); 57 | }; 58 | 59 | export default (monitor = 0) => Widget.Window({ 60 | name: `indicatorBrightness${monitor}`, 61 | monitor, 62 | className: 'indicator', 63 | layer: 'overlay', 64 | visible: true, 65 | anchor: ['top', 'left'], 66 | child: Widget.Box({ 67 | vertical: true, 68 | className: 'osd-window', 69 | css: 'min-height: 2px;', 70 | children: [BrightnessOsd(monitor)] 71 | }) 72 | }); 73 | -------------------------------------------------------------------------------- /src/share/sleex/modules/indicators/main.js: -------------------------------------------------------------------------------- 1 | import Widget from "resource:///com/github/Aylur/ags/widget.js"; 2 | import Indicator from "../../services/indicator.js"; 3 | import ColorScheme from "./colorscheme.js"; 4 | import NotificationPopups from "./notificationpopups.js"; 5 | 6 | export default (monitor = 0) => 7 | Widget.Window({ 8 | name: `indicator${monitor}`, 9 | monitor, 10 | className: "indicator", 11 | layer: "overlay", 12 | visible: true, 13 | anchor: ["top"], 14 | child: Widget.EventBox({ 15 | onHover: () => { 16 | Indicator.popup(-1); 17 | }, 18 | child: Widget.Box({ 19 | vertical: true, 20 | className: "osd-window", 21 | css: "min-height: 2px;", 22 | children: [NotificationPopups(), ColorScheme()], 23 | }), 24 | }), 25 | }); -------------------------------------------------------------------------------- /src/share/sleex/modules/indicators/notificationpopups.js: -------------------------------------------------------------------------------- 1 | // This file is for popup notifications 2 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 3 | import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js'; 4 | const { Box } = Widget; 5 | import Notification from '../.commonwidgets/notification.js'; 6 | 7 | export default () => Box({ 8 | vertical: true, 9 | hpack: 'center', 10 | className: 'osd-notifs spacing-v-5-revealer', 11 | attribute: { 12 | 'map': new Map(), 13 | 'dismiss': (box, id, force = false) => { 14 | if (!id || !box.attribute.map.has(id)) 15 | return; 16 | const notifWidget = box.attribute.map.get(id); 17 | if (notifWidget == null || notifWidget.attribute.hovered && !force) 18 | return; // cuz already destroyed 19 | 20 | notifWidget.revealChild = false; 21 | notifWidget.attribute.destroyWithAnims(); 22 | box.attribute.map.delete(id); 23 | }, 24 | 'notify': (box, id) => { 25 | if (!id || Notifications.dnd) return; 26 | if (!Notifications.getNotification(id)) return; 27 | 28 | box.attribute.map.delete(id); 29 | 30 | const notif = Notifications.getNotification(id); 31 | const newNotif = Notification({ 32 | notifObject: notif, 33 | isPopup: true, 34 | }); 35 | box.attribute.map.set(id, newNotif); 36 | box.pack_end(box.attribute.map.get(id), false, false, 0); 37 | box.show_all(); 38 | }, 39 | }, 40 | setup: (self) => self 41 | .hook(Notifications, (box, id) => box.attribute.notify(box, id), 'notified') 42 | .hook(Notifications, (box, id) => box.attribute.dismiss(box, id), 'dismissed') 43 | .hook(Notifications, (box, id) => box.attribute.dismiss(box, id, true), 'closed') 44 | , 45 | }); 46 | -------------------------------------------------------------------------------- /src/share/sleex/modules/lockscreen/auth.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import pam 4 | import sys 5 | import getpass 6 | 7 | print(pam.authenticate(getpass.getuser(), sys.argv[1])); -------------------------------------------------------------------------------- /src/share/sleex/modules/lockscreen/main.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | import Lockscreen from '../../services/lockscreen.js'; 3 | import Layer from 'gi://GtkLayerShell'; 4 | import GLib from 'gi://GLib'; 5 | import { BarBattery } from '../bar/normal/spaceright.js'; 6 | 7 | const PasswordEntry = () => Widget.Box({ 8 | children: [ 9 | Widget.Entry({ 10 | setup: self => self.hook(Lockscreen, () => self.text = '', 'lock'), 11 | visibility: false, 12 | placeholder_text: 'Password', 13 | on_accept: ({ text }) => Lockscreen.auth(text || ''), 14 | hexpand: true, 15 | }), 16 | ], 17 | }); 18 | 19 | const time = Variable("", { 20 | poll: [ 21 | userOptions.time.interval, 22 | () => GLib.DateTime.new_now_local().format(userOptions.time.format), 23 | ], 24 | }); 25 | 26 | const TopBar = () => Widget.Box({ 27 | children: [ 28 | Widget.Label({label: time.bind()}), 29 | Widget.Box({ hexpand: true }), 30 | BarBattery(), 31 | ] 32 | }); 33 | 34 | const username = () => { 35 | const user = GLib.get_user_name(); 36 | return user.charAt(0).toUpperCase() + user.slice(1); 37 | } 38 | const iconFile = `/var/lib/AccountsService/icons/${GLib.get_user_name()}`; 39 | 40 | const LockscreenBox = () => Widget.Box({ 41 | className: 'lockscreen-container', 42 | vertical: true, 43 | children: [ 44 | TopBar(), 45 | Widget.Box({ 46 | css: `background-image: url('${iconFile}');`, 47 | className: 'avatar', 48 | hpack: 'center', 49 | vpack: 'center', 50 | }), 51 | Widget.Label({ 52 | label: `Welcome back, ${username()}`, 53 | className: 'txt txt-larger', 54 | css: 'margin: 0 2rem 0 2rem;', 55 | }), 56 | PasswordEntry(), 57 | ], 58 | }); 59 | 60 | export default (monitor = 0) => { 61 | const win = Widget.Window({ 62 | name: `lockscreen${monitor}`, 63 | className: 'lockscreen', 64 | monitor, 65 | layer: 'overlay', 66 | visible: false, 67 | setup: self => self.hook(Lockscreen, (_, lock) => self.visible = lock, 'lock'), 68 | child: Widget.Overlay({ 69 | child: Widget.Box({ 70 | css: 'min-width: 3000px; min-height: 2000px;', 71 | child: Widget.Box({ 72 | className: 'content', 73 | vertical: true, 74 | hexpand: true, 75 | vexpand: true, 76 | hpack: 'center', 77 | vpack: 'center', 78 | children: [ 79 | LockscreenBox(), 80 | ], 81 | }), 82 | }), 83 | }), 84 | }); 85 | 86 | Layer.set_keyboard_mode(win, Layer.KeyboardMode.EXCLUSIVE); 87 | return win; 88 | }; -------------------------------------------------------------------------------- /src/share/sleex/modules/overview/actions.js: -------------------------------------------------------------------------------- 1 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 2 | import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; 3 | 4 | function moveClientToWorkspace(address, workspace) { 5 | Utils.execAsync(['bash', '-c', `hyprctl dispatch movetoworkspacesilent ${workspace},address:${address} &`]); 6 | } 7 | 8 | export function dumpToWorkspace(from, to) { 9 | if (from == to) return; 10 | Hyprland.clients.forEach(client => { 11 | if (client.workspace.id == from) { 12 | moveClientToWorkspace(client.address, to); 13 | } 14 | }); 15 | } 16 | 17 | export function swapWorkspace(workspaceA, workspaceB) { 18 | if (workspaceA == workspaceB) return; 19 | const clientsA = []; 20 | const clientsB = []; 21 | Hyprland.clients.forEach(client => { 22 | if (client.workspace.id == workspaceA) clientsA.push(client.address); 23 | if (client.workspace.id == workspaceB) clientsB.push(client.address); 24 | }); 25 | 26 | clientsA.forEach((address) => moveClientToWorkspace(address, workspaceB)); 27 | clientsB.forEach((address) => moveClientToWorkspace(address, workspaceA)); 28 | } -------------------------------------------------------------------------------- /src/share/sleex/modules/overview/main.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | import { SearchAndWindows } from "./windowcontent.js"; 3 | import PopupWindow from '../.widgethacks/popupwindow.js'; 4 | import { clickCloseRegion } from '../.commonwidgets/clickcloseregion.js'; 5 | 6 | export default (id = '') => PopupWindow({ 7 | name: `overview${id}`, 8 | // exclusivity: 'ignore', 9 | keymode: 'on-demand', 10 | visible: false, 11 | anchor: ['top', 'bottom', 'left', 'right'], 12 | layer: 'top', 13 | child: Widget.Box({ 14 | vertical: true, 15 | children: [ 16 | clickCloseRegion({ name: 'overview', multimonitor: false, expand: false }), 17 | Widget.Box({ 18 | children: [ 19 | clickCloseRegion({ name: 'overview', multimonitor: false }), 20 | SearchAndWindows(), 21 | clickCloseRegion({ name: 'overview', multimonitor: false }), 22 | ] 23 | }), 24 | clickCloseRegion({ name: 'overview', multimonitor: false }), 25 | ] 26 | }), 27 | }) 28 | 29 | -------------------------------------------------------------------------------- /src/share/sleex/modules/overview/searchitem.js: -------------------------------------------------------------------------------- 1 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 2 | 3 | export const searchItem = ({ materialIconName, name, actionName, content, onActivate, extraClassName = '', ...rest }) => { 4 | const actionText = Widget.Revealer({ 5 | revealChild: false, 6 | transition: "crossfade", 7 | transitionDuration: userOptions.animations.durationLarge, 8 | child: Widget.Label({ 9 | className: 'overview-search-results-txt txt txt-small txt-action', 10 | label: `${actionName}`, 11 | }) 12 | }); 13 | const actionTextRevealer = Widget.Revealer({ 14 | revealChild: false, 15 | transition: "slide_left", 16 | transitionDuration: userOptions.animations.durationSmall, 17 | child: actionText, 18 | }) 19 | return Widget.Button({ 20 | className: `overview-search-result-btn txt ${extraClassName}`, 21 | onClicked: onActivate, 22 | child: Widget.Box({ 23 | children: [ 24 | Widget.Box({ 25 | vertical: false, 26 | children: [ 27 | Widget.Label({ 28 | className: `icon-material overview-search-results-icon`, 29 | label: `${materialIconName}`, 30 | }), 31 | Widget.Box({ 32 | vertical: true, 33 | children: [ 34 | Widget.Label({ 35 | hpack: 'start', 36 | className: 'overview-search-results-txt txt-smallie txt-subtext', 37 | label: `${name}`, 38 | truncate: "end", 39 | }), 40 | Widget.Label({ 41 | hpack: 'start', 42 | className: 'overview-search-results-txt txt-norm', 43 | label: `${content}`, 44 | truncate: "end", 45 | }), 46 | ] 47 | }), 48 | Widget.Box({ hexpand: true }), 49 | actionTextRevealer, 50 | ], 51 | }) 52 | ] 53 | }), 54 | setup: (self) => self 55 | .on('focus-in-event', (button) => { 56 | actionText.revealChild = true; 57 | actionTextRevealer.revealChild = true; 58 | }) 59 | .on('focus-out-event', (button) => { 60 | actionText.revealChild = false; 61 | actionTextRevealer.revealChild = false; 62 | }) 63 | , 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /src/share/sleex/modules/session/main.js: -------------------------------------------------------------------------------- 1 | import SessionScreen from "./sessionscreen.js"; 2 | import PopupWindow from '../.widgethacks/popupwindow.js'; 3 | 4 | export default (id = 0) => PopupWindow({ // On-screen keyboard 5 | monitor: id, 6 | name: `session${id}`, 7 | visible: false, 8 | keymode: 'on-demand', 9 | layer: 'overlay', 10 | exclusivity: 'ignore', 11 | anchor: ['top', 'bottom', 'left', 'right'], 12 | child: SessionScreen({ id: id }), 13 | }) 14 | -------------------------------------------------------------------------------- /src/share/sleex/modules/sideleft/main.js: -------------------------------------------------------------------------------- 1 | import PopupWindow from '../.widgethacks/popupwindow.js'; 2 | import SidebarLeft from "./sideleft.js"; 3 | import Widget from 'resource:///com/github/Aylur/ags/widget.js'; 4 | const { Box } = Widget; 5 | import clickCloseRegion from '../.commonwidgets/clickcloseregion.js'; 6 | 7 | export default () => PopupWindow({ 8 | keymode: 'on-demand', 9 | anchor: ['left', 'top', 'bottom'], 10 | name: 'sideleft', 11 | layer: 'top', 12 | child: Box({ 13 | children: [ 14 | SidebarLeft(), 15 | clickCloseRegion({ name: 'sideleft', multimonitor: false, fillMonitor: 'horizontal' }), 16 | ] 17 | }) 18 | }); 19 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/README.md: -------------------------------------------------------------------------------- 1 | # scripts folder 2 | - For ARM devices, you have to compile C++ files yourself. If there are none, yippee 3 | - It is advised to use services instead of listening/polling scripts, so everything here are just scripts for actions -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/pywal_to_material.scss: -------------------------------------------------------------------------------- 1 | $primary: lighten($color4, 20%); 2 | $onPrimary: darken($color2, 20%); 3 | $primaryContainer: darken($color2, 10%); 4 | $onPrimaryContainer: lighten($color4, 10%); 5 | $secondary: desaturate(lighten($color5, 20%), 20%); 6 | $onSecondary: desaturate(darken($color3, 20%), 20%); 7 | $secondaryContainer: desaturate(darken($color3, 20%), 20%); 8 | $onSecondaryContainer: desaturate(lighten($color5, 20%), 20%); 9 | $tertiary: adjust-hue(lighten($color4, 20%), 30deg); 10 | $onTertiary: adjust-hue(darken($color2, 20%), 30deg); 11 | $tertiaryContainer: adjust-hue(darken($color2, 10%), 30deg); 12 | $tertiaryContainer: adjust-hue(lighten($color4, 10%), 30deg); 13 | $error: #ffb4a9; 14 | $onError: #680003; 15 | $errorContainer: #930006; 16 | $onErrorContainer: #ffb4a9; 17 | $colorbarbg: $color0; 18 | $background: $color0; 19 | $onBackground: $color7; 20 | $surface: $color0; 21 | $onSurface: $color7; 22 | $surfaceVariant: $color1; 23 | $onSurfaceVariant: $color7; 24 | $outline: $color7; 25 | $shadow: #000000; 26 | $inverseSurface: invert($surface); 27 | $inverseOnSurface: invert($onSurface); 28 | $inversePrimary: invert($primary); 29 | 30 | .primary { color: $primary; } 31 | .onPrimary { color: $onPrimary; } 32 | .primaryContainer { color: $primaryContainer; } 33 | .onPrimaryContainer { color: $onPrimaryContainer; } 34 | .secondary { color: $secondary; } 35 | .onSecondary { color: $onSecondary; } 36 | .secondaryContainer { color: $secondaryContainer; } 37 | .onSecondaryContainer { color: $onSecondaryContainer; } 38 | .tertiary { color: $tertiary; } 39 | .onTertiary { color: $onTertiary; } 40 | .tertiaryContainer { color: $tertiaryContainer; } 41 | .onTertiaryContainer { color: $tertiaryContainer; } 42 | .error { color: $error; } 43 | .onError { color: $onError; } 44 | .errorContainer { color: $errorContainer; } 45 | .onErrorContainer { color: $onErrorContainer; } 46 | .colorbarbg { color: $colorbarbg; } 47 | .background { color: $background; } 48 | .onBackground { color: $onBackground; } 49 | .surface { color: $surface; } 50 | .onSurface { color: $onSurface; } 51 | .surfaceVariant { color: $surfaceVariant; } 52 | .onSurfaceVariant { color: $onSurfaceVariant; } 53 | .outline { color: $outline; } 54 | .shadow { color: $shadow; } 55 | .inverseSurface { color: $inverseSurface; } 56 | .inverseOnSurface { color: $inverseOnSurface; } 57 | .inversePrimary { color: $inversePrimary; } 58 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/randomwall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" 3 | CONFIG_DIR="/usr/share/sleex" 4 | USER_WALLPAPER_DIR="$HOME/.sleex/wallpapers" 5 | $CONFIG_DIR/scripts/color_generation/switchwall.sh "$USER_WALLPAPER_DIR -e .png -e .jpg -e .svg | xargs shuf -n1 -e)" 6 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/schemes/__pycache__/scheme_morevibrant.cpython-313.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/scripts/color_generation/schemes/__pycache__/scheme_morevibrant.cpython-313.pyc -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/schemes/scheme_morevibrant.py: -------------------------------------------------------------------------------- 1 | from materialyoucolor.scheme.dynamic_scheme import DynamicSchemeOptions, DynamicScheme 2 | from materialyoucolor.scheme.variant import Variant 3 | from materialyoucolor.palettes.tonal_palette import TonalPalette 4 | 5 | 6 | class SchemeMoreVibrant(DynamicScheme): 7 | hues = [0.0, 41.0, 61.0, 101.0, 131.0, 181.0, 251.0, 301.0, 360.0] 8 | secondary_rotations = [18.0, 15.0, 10.0, 12.0, 15.0, 18.0, 15.0, 12.0, 12.0] 9 | tertiary_rotations = [35.0, 30.0, 20.0, 25.0, 30.0, 35.0, 30.0, 25.0, 25.0] 10 | 11 | def __init__(self, source_color_hct, is_dark, contrast_level): 12 | super().__init__( 13 | DynamicSchemeOptions( 14 | source_color_hct=source_color_hct, 15 | variant=Variant.VIBRANT, 16 | contrast_level=contrast_level, 17 | is_dark=is_dark, 18 | primary_palette=TonalPalette.from_hue_and_chroma( 19 | source_color_hct.hue, 200.0 20 | ), 21 | secondary_palette=TonalPalette.from_hue_and_chroma( 22 | DynamicScheme.get_rotated_hue( 23 | source_color_hct, 24 | SchemeMoreVibrant.hues, 25 | SchemeMoreVibrant.secondary_rotations, 26 | ), 27 | 32.0, 28 | ), 29 | tertiary_palette=TonalPalette.from_hue_and_chroma( 30 | DynamicScheme.get_rotated_hue( 31 | source_color_hct, 32 | SchemeMoreVibrant.hues, 33 | SchemeMoreVibrant.tertiary_rotations, 34 | ), 35 | 32.0, 36 | ), 37 | neutral_palette=TonalPalette.from_hue_and_chroma( 38 | source_color_hct.hue, 13.0 39 | ), 40 | neutral_variant_palette=TonalPalette.from_hue_and_chroma( 41 | source_color_hct.hue, 15.0 42 | ), 43 | ) 44 | ) 45 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/specials/_material_badapple-l.scss: -------------------------------------------------------------------------------- 1 | $darkmode: false; 2 | $primary: #000000; 3 | $onPrimary: #FFFFFF ; 4 | $primaryContainer: #d4d4d4; 5 | $onPrimaryContainer: #000000; 6 | $secondary: #000000; 7 | $onSecondary: #FFFFFF ; 8 | $secondaryContainer: #bebebe; 9 | $onSecondaryContainer: #000000; 10 | $tertiary: #000000; 11 | $onTertiary: #FFFFFF ; 12 | $tertiaryContainer: #FFFFFF ; 13 | $onTertiaryContainer: #000000; 14 | $error: #000000; 15 | $onError: #FFFFFF ; 16 | $errorContainer: #FFFFFF ; 17 | $onErrorContainer: #000000; 18 | $colorbarbg: #FFFFFF ; 19 | $background: #FFFFFF ; 20 | $onBackground: #000000; 21 | $surface: #f0f0f0; 22 | $onSurface: #000000; 23 | $surfaceVariant: #dddddd; 24 | $onSurfaceVariant: #000000; 25 | $outline: #525252; 26 | $shadow: #000000 ; 27 | $inverseSurface: #000000; 28 | $inverseOnSurface: #FFFFFF; 29 | $inversePrimary: #000000; 30 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/specials/_material_badapple.scss: -------------------------------------------------------------------------------- 1 | $darkmode: true; 2 | $primary: #e2e2e2; 3 | $onPrimary: #000000; 4 | $primaryContainer: #6b6b6b; 5 | $onPrimaryContainer: #e2e2e2; 6 | $secondary: #e2e2e2; 7 | $onSecondary: #000000; 8 | $secondaryContainer: #313131; 9 | $onSecondaryContainer: #e2e2e2; 10 | $tertiary: #e2e2e2; 11 | $onTertiary: #000000; 12 | $tertiaryContainer: #000000; 13 | $onTertiaryContainer: #e2e2e2; 14 | $error: #e2e2e2; 15 | $onError: #000000; 16 | $errorContainer: #000000; 17 | $onErrorContainer: #e2e2e2; 18 | $colorbarbg: #000000; 19 | $background: #000000; 20 | $onBackground: #e2e2e2; 21 | $surface: #161616; 22 | $onSurface: #e2e2e2; 23 | $surfaceVariant: #242424; 24 | $onSurfaceVariant: #e2e2e2; 25 | $outline: #a1a1a1; 26 | $shadow: #000000; 27 | $inverseSurface: #e2e2e2; 28 | $inverseOnSurface: #000000; 29 | $inversePrimary: #e2e2e2; 30 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/switchcolor.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" 4 | XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" 5 | XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" 6 | CONFIG_DIR="/usr/share/sleex" 7 | CACHE_DIR="$XDG_CACHE_HOME/ags" 8 | STATE_DIR="$XDG_STATE_HOME/ags" 9 | 10 | COLORMODE_FILE_DIR="$STATE_DIR/user/colormode.txt" 11 | 12 | if [ "$1" == "--pick" ]; then 13 | color=$(hyprpicker --no-fancy) 14 | elif [[ "$1" = "#"* ]]; then # this is a color 15 | color=$1 16 | else 17 | color=$(cut -f1 "$STATE_DIR/user/color.txt") 18 | fi 19 | 20 | sed -i "1s/.*/$color/" "$STATE_DIR/user/color.txt" 21 | 22 | # Generate colors for ags n stuff 23 | "$CONFIG_DIR"/scripts/color_generation/colorgen.sh "${color}" --apply 24 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/color_generation/switchwall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" 4 | CONFIG_DIR="/usr/share/sleex" 5 | 6 | switch() { 7 | imgpath=$1 8 | read scale screenx screeny screensizey < <(hyprctl monitors -j | jq '.[] | select(.focused) | .scale, .x, .y, .height' | xargs) 9 | cursorposx=$(hyprctl cursorpos -j | jq '.x' 2>/dev/null) || cursorposx=960 10 | cursorposx=$(bc <<< "scale=0; ($cursorposx - $screenx) * $scale / 1") 11 | cursorposy=$(hyprctl cursorpos -j | jq '.y' 2>/dev/null) || cursorposy=540 12 | cursorposy=$(bc <<< "scale=0; ($cursorposy - $screeny) * $scale / 1") 13 | cursorposy_inverted=$((screensizey - cursorposy)) 14 | 15 | if [ "$imgpath" == '' ]; then 16 | echo 'Aborted' 17 | exit 0 18 | fi 19 | 20 | # ags run-js "wallpaper.set('')" 21 | # sleep 0.1 && ags run-js "wallpaper.set('${imgpath}')" & 22 | swww img "$imgpath" --transition-step 100 --transition-fps 120 \ 23 | --transition-type grow --transition-angle 30 --transition-duration 1 \ 24 | --transition-pos "$cursorposx, $cursorposy_inverted" 25 | } 26 | 27 | imgpath="" 28 | 29 | while [[ "$#" -gt 0 ]]; do 30 | case $1 in 31 | --noswitch) noswitch=true ;; 32 | --path) imgpath="$2"; shift ;; 33 | *) imgpath="$1" ;; 34 | esac 35 | shift 36 | done 37 | 38 | if [ "$noswitch" == true ]; then 39 | imgpath=$(swww query | awk -F 'image: ' '{print $2}') 40 | # imgpath=$(ags run-js 'wallpaper.get(0)') 41 | elif [[ "$imgpath" ]]; then 42 | switch "$imgpath" 43 | else 44 | # Select and set image (hyprland) 45 | cd "$(xdg-user-dir PICTURES)" || return 1 46 | switch "$(yad --width 1200 --height 800 --file --add-preview --large-preview --title='Choose wallpaper')" 47 | fi 48 | 49 | # Generate colors for ags n stuff 50 | "$CONFIG_DIR"/scripts/color_generation/colorgen.sh "${imgpath}" --apply --smart 51 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/dnd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # File to track DND state 4 | STATE_FILE="$HOME/.cache/ags/dnd_state" 5 | 6 | if [ ! -f $STATE_FILE ]; then 7 | # If state file doesn't exist, create it and enable DND 8 | touch $STATE_FILE 9 | dbus-send --session --dest=org.freedesktop.Notifications \ 10 | --type=method_call /org/freedesktop/Notifications \ 11 | org.freedesktop.Notifications.Inhibit string:"DoNotDisturb" 12 | echo "Do Not Disturb Enabled" 13 | else 14 | # If state file exists, remove it and disable DND 15 | rm $STATE_FILE 16 | dbus-send --session --dest=org.freedesktop.Notifications \ 17 | --type=method_call /org/freedesktop/Notifications \ 18 | org.freedesktop.Notifications.UnInhibit string:"DoNotDisturb" 19 | echo "Do Not Disturb Disabled" 20 | fi 21 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/firstRun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script is run the first time the user logs in after installing Sleex. 4 | # It sets up the user's environment to use Sleex. 5 | 6 | echo 'Setting up Sleex environment...' 7 | echo 'true' > ~/.local/state/ags/user/show_monitor.txt 8 | echo 'true' > ~/.local/state/ags/user/show_timedate.txt 9 | echo 'true' > ~/.local/state/ags/user/show_workspaces.txt 10 | echo 'true' > ~/.local/state/ags/user/show_wintitle.txt 11 | 12 | 13 | CONFIG_FILE="$HOME/.config/hypr/custom/general.conf" 14 | KEYBINDS_DIR="$HOME/.config/hypr/hyprland" 15 | VC_KEYMAP=$(grep -i KEYMAP /etc/vconsole.conf | cut -d= -f2 | tr -d '"') 16 | LAYOUT=$(echo "$VC_KEYMAP" | awk '{print tolower($0)}') 17 | 18 | echo "Setting keyboard layout to '$LAYOUT' in $CONFIG_FILE." 19 | 20 | if grep -q "^input:kb_layout" "$CONFIG_FILE"; then 21 | sed -i "s/^input:kb_layout.*/input:kb_layout = $LAYOUT/" "$CONFIG_FILE" 22 | else 23 | echo "input:kb_layout = $LAYOUT" >> "$CONFIG_FILE" 24 | fi 25 | 26 | echo "Applying keybinds configuration in $KEYBINDS_DIR." 27 | 28 | if [[ "$LAYOUT" == "us" ]]; then 29 | mv -f "$KEYBINDS_DIR/keybinds_us.conf" "$KEYBINDS_DIR/keybinds.conf" 30 | echo "Switched to US keybinds." 31 | elif [[ "$LAYOUT" == "fr" ]]; then 32 | mv -f "$KEYBINDS_DIR/keybinds_fr.conf" "$KEYBINDS_DIR/keybinds.conf" 33 | echo "Switched to FR keybinds." 34 | else 35 | echo "Unknown layout: $LAYOUT – applying US keybinds." 36 | mv -f "$KEYBINDS_DIR/keybinds_us.conf" "$KEYBINDS_DIR/keybinds.conf" 37 | 38 | fi 39 | 40 | hyprctl reload 41 | 42 | echo 'Complete!' -------------------------------------------------------------------------------- /src/share/sleex/scripts/generate_thumbnails.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | 5 | THUMBNAIL_DIR="$HOME/.sleex/wallpapers/thumbnails" 6 | WALLPAPER_DIR="$HOME/.sleex/wallpapers" 7 | 8 | mkdir -p "$THUMBNAIL_DIR" 9 | 10 | for image in "$WALLPAPER_DIR"/*.{jpg,JPG,jpeg,JPEG,png,PNG,gif,GIF,webp,WEBP}; do 11 | [ -e "$image" ] || continue 12 | 13 | filename=$(basename "$image") 14 | 15 | if [ -f "$THUMBNAIL_DIR/$filename" ]; then 16 | echo "Skipping $filename - thumbnail already exists" 17 | continue 18 | fi 19 | 20 | if [[ "$image" =~ \.gif$|\.GIF$ ]]; then 21 | magick "$image[0]" -resize 150x90^ -gravity center -extent 150x90 "$THUMBNAIL_DIR/$filename" 22 | else 23 | magick "$image" -resize 150x90^ -gravity center -extent 150x90 "$THUMBNAIL_DIR/$filename" 24 | fi 25 | done 26 | 27 | notify-send "Thumbnails generation complete" -------------------------------------------------------------------------------- /src/share/sleex/scripts/hyprland/workspace_action.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | hyprctl dispatch "$1" $(((($(hyprctl activeworkspace -j | jq -r .id) - 1) / 10) * 10 + $2)) 3 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/lockscreen/battery-status: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # status="$(acpi -b | grep -ioh "\w*charging\w*")" 4 | # level="$(acpi -b | grep -o -P "[0-9]+(?=%)")" 5 | 6 | status="$(cat /sys/class/power_supply/BAT0/status)" 7 | level="$(cat /sys/class/power_supply/BAT0/capacity)" 8 | 9 | if [[ ("$status" == "Discharging") || ("$status" == "Full") ]]; then 10 | if [[ "$level" -eq "0" ]]; then 11 | printf " " 12 | elif [[ ("$level" -ge "0") && ("$level" -le "25") ]]; then 13 | printf " " 14 | elif [[ ("$level" -ge "25") && ("$level" -le "50") ]]; then 15 | printf " " 16 | elif [[ ("$level" -ge "50") && ("$level" -le "75") ]]; then 17 | printf " " 18 | elif [[ ("$level" -ge "75") && ("$level" -le "100") ]]; then 19 | printf " " 20 | fi 21 | elif [[ "$status" == "Charging" ]]; then 22 | printf " " 23 | fi 24 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/lockscreen/song-status: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | player_name=$(playerctl metadata --format '{{playerName}}') 3 | player_status=$(playerctl status) 4 | 5 | if [[ "$player_status" == "Playing" ]]; then 6 | song_info=$(playerctl metadata --format '{{title}} | {{artist}}') 7 | fi 8 | 9 | echo "$song_info" 10 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/network_scripts/network_bandwidth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from time import sleep 4 | import sys 5 | import psutil 6 | 7 | try: 8 | direction = sys.argv[1] 9 | except IndexError: 10 | direction = "recv" 11 | 12 | init_bytes = final_bytes = 0 13 | 14 | match direction: 15 | case "recv": 16 | init_bytes = psutil.net_io_counters().bytes_recv 17 | sleep(1) 18 | final_bytes = psutil.net_io_counters().bytes_recv 19 | 20 | case "sent": 21 | init_bytes = psutil.net_io_counters().bytes_sent 22 | sleep(1) 23 | final_bytes = psutil.net_io_counters().bytes_sent 24 | 25 | case _: 26 | print(f"wrong direction: {direction}") 27 | sys.exit() 28 | 29 | i = 0 30 | divider = 1000 31 | bandwidth = int((final_bytes - init_bytes)) 32 | units = ["B", "KB", "MB", "GB", "TB", "PB", "EB"] 33 | 34 | while bandwidth >= divider: 35 | i += 1 36 | bandwidth = bandwidth / divider 37 | 38 | print(f"{bandwidth:.1f}" + units[i] + "/s") 39 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/record-script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | getdate() { 4 | date '+%Y-%m-%d_%H.%M.%S' 5 | } 6 | getaudiooutput() { 7 | pactl list sources | grep 'Name' | grep 'monitor' | cut -d ' ' -f2 8 | } 9 | getactivemonitor() { 10 | hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name' 11 | } 12 | 13 | mkdir -p "$(xdg-user-dir VIDEOS)" 14 | cd "$(xdg-user-dir VIDEOS)" || exit 15 | if pgrep wf-recorder > /dev/null; then 16 | notify-send "Recording Stopped" "Stopped" -a 'record-script.sh' & 17 | pkill wf-recorder & 18 | else 19 | notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'record-script.sh' 20 | if [[ "$1" == "--sound" ]]; then 21 | wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" --audio="$(getaudiooutput)" & disown 22 | elif [[ "$1" == "--fullscreen-sound" ]]; then 23 | wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio="$(getaudiooutput)" & disown 24 | elif [[ "$1" == "--fullscreen" ]]; then 25 | wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t & disown 26 | else 27 | wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" & disown 28 | fi 29 | fi 30 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/sway/swayToRelativeWs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Check if sway is running 4 | if ! pgrep -x sway > /dev/null; then 5 | echo "Sway is not running" 6 | exit 1 7 | fi 8 | 9 | 10 | # Get the current workspace number 11 | current=$(swaymsg -t get_workspaces | jq '.[] | select(.focused==true) | .num') 12 | 13 | # Check if a number was passed as an argument 14 | if [[ "$1" =~ ^[+-]?[0-9]+$ ]]; then 15 | new_workspace=$((current + $1)) 16 | else 17 | new_workspace=$((current + 1)) 18 | fi 19 | 20 | # Check if the new workspace number is out of bounds 21 | if [[ $new_workspace -lt 1 ]]; then 22 | exit 0 23 | fi 24 | 25 | # Switch to the new workspace 26 | if [[ $2 == 'move' ]]; then 27 | swaymsg move container to workspace $new_workspace 28 | else 29 | swaymsg workspace $new_workspace 30 | fi 31 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/templates/fuzzel/fuzzel.ini: -------------------------------------------------------------------------------- 1 | font=Gabarito 2 | terminal=foot -e 3 | prompt=">> " 4 | layer=overlay 5 | 6 | [colors] 7 | background={{ $background }}ff 8 | text={{ $onBackground }}ff 9 | selection={{ $surfaceVariant }}ff 10 | selection-text={{ $onSurfaceVariant }}ff 11 | border={{ $surfaceVariant }}dd 12 | match={{ $primary }}ff 13 | selection-match={{ $primary }}ff 14 | 15 | 16 | [border] 17 | radius=17 18 | width=1 19 | 20 | [dmenu] 21 | exit-immediately-if-empty=yes 22 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/templates/gtk/gtk-colors.css: -------------------------------------------------------------------------------- 1 | /* 2 | * GTK Colors 3 | */ 4 | 5 | @define-color accent_color {{ $primary }}; 6 | @define-color accent_fg_color {{ $onPrimary }}; 7 | @define-color accent_bg_color {{ $primary }}; 8 | @define-color window_bg_color {{ $background }}; 9 | @define-color window_fg_color {{ $onBackground }}; 10 | @define-color headerbar_bg_color {{ $surfaceDim }}; 11 | @define-color headerbar_fg_color {{ $onSurface }}; 12 | @define-color popover_bg_color {{ $surfaceDim }}; 13 | @define-color popover_fg_color {{ $onSurface }}; 14 | @define-color view_bg_color {{ $surface }}; 15 | @define-color view_fg_color {{ $onSurface }}; 16 | @define-color card_bg_color {{ $surface }}; 17 | @define-color card_fg_color {{ $onSurface }}; 18 | @define-color sidebar_bg_color @window_bg_color; 19 | @define-color sidebar_fg_color @window_fg_color; 20 | @define-color sidebar_border_color @window_bg_color; 21 | @define-color sidebar_backdrop_color @window_bg_color; -------------------------------------------------------------------------------- /src/share/sleex/scripts/templates/terminal/scheme-base.json: -------------------------------------------------------------------------------- 1 | { 2 | "dark": { 3 | "term0" : "#282828", 4 | "term1" : "#CC241D", 5 | "term2" : "#98971A", 6 | "term3" : "#D79921", 7 | "term4" : "#458588", 8 | "term5" : "#B16286", 9 | "term6" : "#689D6A", 10 | "term7" : "#A89984", 11 | "term8" : "#928374", 12 | "term9" : "#FB4934", 13 | "term10" : "#B8BB26", 14 | "term11" : "#FABD2F", 15 | "term12" : "#83A598", 16 | "term13" : "#D3869B", 17 | "term14" : "#8EC07C", 18 | "term15" : "#EBDBB2" 19 | }, 20 | "light": { 21 | "term0" : "#FDF9F3", 22 | "term1" : "#FF6188", 23 | "term2" : "#A9DC76", 24 | "term3" : "#FC9867", 25 | "term4" : "#FFD866", 26 | "term5" : "#F47FD4", 27 | "term6" : "#78DCE8", 28 | "term7" : "#333034", 29 | "term8" : "#121212", 30 | "term9" : "#FF6188", 31 | "term10" : "#A9DC76", 32 | "term11" : "#FC9867", 33 | "term12" : "#FFD866", 34 | "term13" : "#F47FD4", 35 | "term14" : "#78DCE8", 36 | "term15" : "#333034" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/templates/terminal/scheme-monochrome.json: -------------------------------------------------------------------------------- 1 | { 2 | "dark": { 3 | "term0": "#000000", 4 | "term1": "#FFFFFF", 5 | "term2": "#CCCCCC", 6 | "term3": "#8f8f8f", 7 | "term4": "#FFFFFF", 8 | "term5": "#111111", 9 | "term6": "#CCCCCC", 10 | "term7": "#FFFFFF", 11 | "term8": "#404040", 12 | "term9": "#CCCCCC", 13 | "term10": "#FFFFFF", 14 | "term11": "#909090", 15 | "term12": "#CCCCCC", 16 | "term13": "#808080", 17 | "term14": "#CCCCCC", 18 | "term15": "#FFFFFF" 19 | }, 20 | "light": { 21 | "term0": "#EAE9EA", 22 | "term1": "#777777", 23 | "term2": "#000000", 24 | "term3": "#000000", 25 | "term4": "#000000", 26 | "term5": "#000000", 27 | "term6": "#000000", 28 | "term7": "#202020", 29 | "term8": "#000000", 30 | "term9": "#000000", 31 | "term10": "#CCCCCC", 32 | "term11": "#808080", 33 | "term12": "#CCCCCC", 34 | "term13": "#FFFFFF" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/templates/terminal/sequences.txt: -------------------------------------------------------------------------------- 1 | ]4;0;#$term0 #\]4;1;#$term1 #\]4;2;#$term2 #\]4;3;#$term3 #\]4;4;#$term4 #\]4;5;#$term5 #\]4;6;#$term6 #\]4;7;#$term7 #\]4;8;#$term8 #\]4;9;#$term9 #\]4;10;#$term10 #\]4;11;#$term11 #\]4;12;#$term12 #\]4;13;#$term13 #\]4;14;#$term14 #\]4;15;#$term15 #\]10;#$term7 #\]11;[$alpha]#$term0 #\]12;#$term7 #\]13;#$term7 #\]17;#$term7 #\]19;#$term0 #\]4;232;#$term7 #\]4;256;#$term7 #\]708;[$alpha]#$term0 #\ 2 | -------------------------------------------------------------------------------- /src/share/sleex/scripts/wayland-idle-inhibitor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from dataclasses import dataclass 5 | from signal import SIGINT, SIGTERM, signal 6 | from threading import Event 7 | import setproctitle 8 | 9 | from pywayland.client.display import Display 10 | from pywayland.protocol.idle_inhibit_unstable_v1.zwp_idle_inhibit_manager_v1 import ( 11 | ZwpIdleInhibitManagerV1, 12 | ) 13 | from pywayland.protocol.wayland.wl_compositor import WlCompositor 14 | from pywayland.protocol.wayland.wl_registry import WlRegistryProxy 15 | from pywayland.protocol.wayland.wl_surface import WlSurface 16 | 17 | 18 | @dataclass 19 | class GlobalRegistry: 20 | surface: WlSurface | None = None 21 | inhibit_manager: ZwpIdleInhibitManagerV1 | None = None 22 | 23 | 24 | def handle_registry_global( 25 | wl_registry: WlRegistryProxy, id_num: int, iface_name: str, version: int 26 | ) -> None: 27 | global_registry: GlobalRegistry = wl_registry.user_data or GlobalRegistry() 28 | 29 | if iface_name == "wl_compositor": 30 | compositor = wl_registry.bind(id_num, WlCompositor, version) 31 | global_registry.surface = compositor.create_surface() # type: ignore 32 | elif iface_name == "zwp_idle_inhibit_manager_v1": 33 | global_registry.inhibit_manager = wl_registry.bind( 34 | id_num, ZwpIdleInhibitManagerV1, version 35 | ) 36 | 37 | 38 | def main() -> None: 39 | done = Event() 40 | signal(SIGINT, lambda _, __: done.set()) 41 | signal(SIGTERM, lambda _, __: done.set()) 42 | 43 | global_registry = GlobalRegistry() 44 | 45 | display = Display() 46 | display.connect() 47 | 48 | registry = display.get_registry() # type: ignore 49 | registry.user_data = global_registry 50 | registry.dispatcher["global"] = handle_registry_global 51 | 52 | def shutdown() -> None: 53 | display.dispatch() 54 | display.roundtrip() 55 | display.disconnect() 56 | 57 | display.dispatch() 58 | display.roundtrip() 59 | 60 | if global_registry.surface is None or global_registry.inhibit_manager is None: 61 | print("Wayland seems not to support idle_inhibit_unstable_v1 protocol.") 62 | shutdown() 63 | sys.exit(1) 64 | 65 | inhibitor = global_registry.inhibit_manager.create_inhibitor( # type: ignore 66 | global_registry.surface 67 | ) 68 | 69 | display.dispatch() 70 | display.roundtrip() 71 | 72 | print("Inhibiting idle...") 73 | done.wait() 74 | print("Shutting down...") 75 | 76 | inhibitor.destroy() 77 | 78 | shutdown() 79 | 80 | 81 | if __name__ == "__main__": 82 | setproctitle.setproctitle("wayland-idle-inhibitor.py") 83 | main() 84 | -------------------------------------------------------------------------------- /src/share/sleex/scss/_desktopbackground.scss: -------------------------------------------------------------------------------- 1 | .bg-wallpaper-transition { 2 | transition: 1000ms cubic-bezier(0.05, 0.7, 0.1, 1); 3 | font-size: 1px; 4 | } 5 | 6 | @mixin bg-textshadow { 7 | // text-shadow: mix($shadow, $secondaryContainer, 50%) 1px 0px 3px; 8 | } 9 | 10 | .bg-time-box { 11 | @include large-rounding; 12 | margin: 2.045rem; 13 | padding: 0.682rem; 14 | margin-bottom: 15rem; 15 | } 16 | 17 | .bg-weather-box { 18 | padding: 0.682rem; 19 | margin-bottom: 15rem; 20 | } 21 | 22 | .bg-time-clock { 23 | @include titlefont; 24 | @include bg-textshadow; 25 | font-weight: 800; 26 | font-size: 10.091rem; 27 | color: $onLayer0; 28 | } 29 | 30 | .bg-time-date { 31 | @include titlefont; 32 | @include bg-textshadow; 33 | font-size: 2.591rem; 34 | color: $onLayer0; 35 | } 36 | 37 | .bg-distro-box { 38 | @include large-rounding; 39 | margin: 2.045rem; 40 | padding: 0.682rem; 41 | } 42 | 43 | .bg-distro-txt { 44 | @include titlefont; 45 | @include bg-textshadow; 46 | font-size: 1.432rem; 47 | color: $onLayer0; 48 | } 49 | 50 | .bg-distro-name { 51 | @include titlefont; 52 | @include bg-textshadow; 53 | font-size: 1.432rem; 54 | color: $onSecondaryContainer; 55 | } 56 | 57 | .bg-graph { 58 | color: rgba(255, 255, 255, 0.5); 59 | border-radius: 0.614rem; 60 | border: 0.682rem solid; 61 | } 62 | 63 | .bg-quicklaunch-title { 64 | @include mainfont; 65 | color: $onSurfaceVariant; 66 | } 67 | 68 | .bg-quicklaunch-btn { 69 | @include mainfont; 70 | @include full-rounding; 71 | background-color: $layer2; 72 | color: $onLayer2; 73 | min-width: 4.432rem; 74 | min-height: 2.045rem; 75 | padding: 0.273rem 0.682rem; 76 | } 77 | 78 | .bg-quicklaunch-btn:hover, 79 | .bg-quicklaunch-btn:focus { 80 | background-color: $layer2Hover; 81 | } 82 | 83 | .bg-quicklaunch-btn:active { 84 | background-color: $layer2Active; 85 | } 86 | 87 | .bg-system-bg { 88 | @include normal-rounding; 89 | // background-color: $background; 90 | } 91 | 92 | .bg-system-circprog { 93 | @include fluent_decel_long; 94 | min-width: 0.205rem; // Trough stroke width 95 | min-height: 4.091rem; // Diameter 96 | font-size: 0px; 97 | padding: 0rem; 98 | background-color: $layer2; 99 | } 100 | 101 | .desktop-weather { 102 | @include normal-rounding; 103 | margin: 2.045rem; 104 | padding: 1rem; 105 | background-color: $layer0; 106 | font-size: 1.5rem; 107 | } 108 | 109 | .txt-weather-location { 110 | margin: 0.682rem 0; 111 | } 112 | 113 | .hours-circprog { 114 | @include fluent_decel_long; 115 | min-width: 1.136rem; // line width 116 | min-height: 15.636rem; 117 | padding: 0rem; 118 | background-color: $battLayer2; 119 | color: $battOnLayer2; 120 | } 121 | 122 | .minutes-circprog { 123 | @include fluent_decel_long; 124 | min-width: 1.136rem; // line width 125 | min-height: 11.636rem; 126 | padding: 0rem; 127 | background-color: $battLayer2; 128 | color: $battOnLayer2; 129 | } 130 | -------------------------------------------------------------------------------- /src/share/sleex/scss/_dock.scss: -------------------------------------------------------------------------------- 1 | .dock-bg { 2 | @include elevation2; 3 | background-color: $layer0; 4 | padding: 0.682rem; 5 | border-radius: $rounding_large $rounding_large 0rem 0rem; 6 | margin-bottom: 0; 7 | } 8 | 9 | .dock-app-btn-animate { 10 | transition-property: background-color; 11 | transition-duration: 0.5s; 12 | } 13 | 14 | .dock-app-btn { 15 | @include normal-rounding; 16 | padding: 0.273rem; 17 | } 18 | 19 | .pinned-dock-app-btn { 20 | @include normal-rounding; 21 | padding: 0.273rem; 22 | background-color: $layer0Hover; 23 | } 24 | 25 | .dock-app-btn:hover, 26 | .dock-app-btn:focus { 27 | background-color: $layer0Hover; 28 | } 29 | 30 | .dock-app-btn:active { 31 | background-color: $layer0Active; 32 | } 33 | 34 | .dock-app-icon { 35 | min-width: 3.409rem; 36 | min-height: 3.409rem; 37 | font-size: 3.409rem; 38 | } 39 | 40 | .dock-separator { 41 | min-width: 0.068rem; 42 | background-color: $outline; 43 | } -------------------------------------------------------------------------------- /src/share/sleex/scss/_lockscreen.scss: -------------------------------------------------------------------------------- 1 | .lockscreen { 2 | background-color: rgba(0, 0, 0, 0.25); 3 | 4 | spinner { 5 | margin-top: 0.625rem; 6 | } 7 | 8 | entry { 9 | background-color: $layer1; 10 | margin-top: 1rem; 11 | padding: 1rem; 12 | min-height: 20px; 13 | @include small-rounding; 14 | } 15 | 16 | .avatar { 17 | border-radius: 99px; 18 | min-width: 7rem; 19 | min-height: 7rem; 20 | margin: 1rem; 21 | background-size: cover; 22 | } 23 | } 24 | 25 | .lockscreen-container { 26 | background-color: $layer0; 27 | padding: 2rem; 28 | border: none; 29 | @include normal-rounding; 30 | } -------------------------------------------------------------------------------- /src/share/sleex/scss/_osk.scss: -------------------------------------------------------------------------------- 1 | $osk_key_height: 2.5rem; 2 | $osk_key_width: 2.5rem; 3 | $osk_key_padding: 0.188rem; 4 | $osk_key_rounding: 0.545rem; 5 | $osk_key_fontsize: 1.091rem; 6 | 7 | .osk-window { 8 | // @include menu_decel_fast; 9 | @include large-rounding; 10 | @include elevation-border; 11 | @include elevation2; 12 | // min-height: 29.591rem; 13 | // min-width: 50rem; 14 | background-color: $layer0; 15 | } 16 | 17 | .osk-body { 18 | padding: 1.023rem; 19 | padding-top: 0rem; 20 | } 21 | 22 | .osk-show { 23 | @include menu_decel_fast; 24 | } 25 | 26 | .osk-hide { 27 | margin-top: 30.682rem; 28 | margin-bottom: -30.682rem; 29 | // opacity: 0; 30 | @include menu_accel_fast; 31 | } 32 | 33 | .osk-dragline { 34 | @include full-rounding; 35 | background-color: $onLayer0Inactive; 36 | min-height: 0.273rem; 37 | min-width: 10.227rem; 38 | margin-top: 0.545rem; 39 | margin-bottom: 0.205rem; 40 | } 41 | 42 | .osk-key { 43 | border-radius: $osk_key_rounding; 44 | background-color: $layer1; 45 | color: $onLayer1; 46 | padding: $osk_key_padding; 47 | font-weight: 500; 48 | font-size: $osk_key_fontsize; 49 | } 50 | 51 | .osk-key:hover, 52 | .osk-key:focus { 53 | background-color: $layer1Hover; 54 | } 55 | 56 | .osk-key:active { 57 | background-color: $layer1Active; 58 | font-size: $osk_key_fontsize; 59 | } 60 | 61 | .osk-key-active { 62 | background-color: $layer1Active; 63 | } 64 | 65 | .osk-key-normal { 66 | min-width: $osk_key_width; 67 | min-height: $osk_key_height; 68 | } 69 | 70 | .osk-key-fn { 71 | min-width: $osk_key_width * 1.005; 72 | min-height: calc($osk_key_height / 2); // dart-sass 73 | // min-height: $osk_key_height / 2; // sassc 74 | } 75 | 76 | .osk-key-tab { 77 | min-width: $osk_key_width * 1.6; 78 | min-height: $osk_key_height; 79 | } 80 | 81 | .osk-key-caps { 82 | min-width: $osk_key_width * 1.9; 83 | min-height: $osk_key_height; 84 | } 85 | 86 | .osk-key-shift { 87 | min-width: $osk_key_width * 2.5; 88 | min-height: $osk_key_height; 89 | } 90 | 91 | .osk-key-control { 92 | min-width: $osk_key_width * 1.3; 93 | min-height: $osk_key_height; 94 | } 95 | 96 | .osk-control-button { 97 | border-radius: $osk_key_rounding; 98 | background-color: $layer1; 99 | color: $onLayer1; 100 | font-weight: 500; 101 | font-size: $osk_key_fontsize; 102 | padding: 0.682rem; 103 | } 104 | 105 | .osk-control-button:hover, 106 | .osk-control-button:focus { 107 | background-color: $layer1Hover; 108 | } 109 | 110 | .osk-control-button:active { 111 | background-color: $layer1Active; 112 | font-size: $osk_key_fontsize; 113 | } 114 | 115 | .osk-key-empty, .osk-key-empty:hover, .osk-key-empty:focus { 116 | min-width: $osk_key_width; 117 | min-height: $osk_key_height; 118 | background-color: transparent; 119 | } 120 | -------------------------------------------------------------------------------- /src/share/sleex/scss/_overview.scss: -------------------------------------------------------------------------------- 1 | .overview-window { 2 | margin-top: 2.727rem; 3 | } 4 | 5 | .overview-search-box { 6 | @include element_decel; 7 | @include large-rounding; 8 | @include elevation-border; 9 | @include elevation2; 10 | min-width: 13.636rem; 11 | min-height: 3.409rem; 12 | padding: 0rem 1.364rem; 13 | padding-right: 2.864rem; 14 | background-color: $background; 15 | color: $onBackground; 16 | 17 | selection { 18 | background-color: $secondary; 19 | color: $onSecondary; 20 | } 21 | 22 | caret-color: transparent; 23 | } 24 | 25 | .overview-search-box-extended { 26 | min-width: 25.909rem; 27 | caret-color: $onSecondaryContainer; 28 | } 29 | 30 | .overview-search-prompt { 31 | color: $subtext; 32 | } 33 | 34 | .overview-search-icon { 35 | margin: 0rem 1.023rem; 36 | } 37 | 38 | .overview-search-prompt-box { 39 | margin-left: -18.545rem; 40 | margin-right: $elevation_margin + 0.068rem; 41 | } 42 | 43 | .overview-search-icon-box { 44 | margin-left: -18.545rem; 45 | margin-right: $elevation_margin + 0.068rem; 46 | } 47 | 48 | .overview-search-results { 49 | // min-height: 2.813rem; 50 | // min-height: 37.5rem; 51 | @include large-rounding; 52 | @include elevation-border; 53 | @include elevation2; 54 | min-width: 28.773rem; 55 | padding: 0.682rem; 56 | background-color: $layer0; 57 | color: $onLayer0; 58 | } 59 | 60 | .overview-search-results-icon { 61 | margin: 0rem 0.682rem; 62 | font-size: 2.386rem; 63 | min-width: 2.386rem; 64 | min-height: 2.386rem; 65 | } 66 | 67 | .overview-search-results-txt { 68 | margin-right: 0.682rem; 69 | } 70 | 71 | .overview-search-results-txt-cmd { 72 | margin-right: 0.682rem; 73 | @include techfont; 74 | font-size: 1.227rem; 75 | } 76 | 77 | .overview-search-result-btn { 78 | @include normal-rounding; 79 | padding: 0.341rem; 80 | min-width: 2.386rem; 81 | min-height: 2.386rem; 82 | 83 | caret-color: transparent; 84 | } 85 | 86 | .overview-search-result-btn:hover, 87 | .overview-search-result-btn:focus { 88 | background-color: $layer2; 89 | } 90 | 91 | .overview-search-result-btn:active { 92 | background-color: $layer2Hover; 93 | } 94 | 95 | .overview-tasks { 96 | @include large-rounding; 97 | @include elevation-border; 98 | @include elevation2; 99 | padding: 0.341rem; 100 | background-color: $background; 101 | color: $onBackground; 102 | } 103 | 104 | .overview-tasks-workspace { 105 | @include normal-rounding; 106 | // @include elevation-border; 107 | margin: 0.341rem; 108 | background-color: $layer1; 109 | } 110 | 111 | .overview-tasks-workspace-number { 112 | @include mainfont; 113 | color: $onSurfaceVariant; 114 | } 115 | 116 | .overview-tasks-window { 117 | @include normal-rounding; 118 | @include menu_decel; 119 | background-color: transparentize($layer3, 0.2); 120 | color: $onSurface; 121 | border: 0.068rem solid $surfaceContainerHighest; 122 | } 123 | 124 | .overview-tasks-window:hover, 125 | .overview-tasks-window:focus { 126 | background-color: transparentize($secondaryContainer, 0.3); 127 | } 128 | 129 | .overview-tasks-window:active { 130 | background-color: transparentize($secondaryContainer, 0); 131 | } 132 | 133 | .overview-tasks-window-selected { 134 | background-color: transparentize($secondaryContainer, 0.3); 135 | } 136 | 137 | .overview-tasks-window-dragging { 138 | opacity: 0.2; 139 | } 140 | -------------------------------------------------------------------------------- /src/share/sleex/scss/_session.scss: -------------------------------------------------------------------------------- 1 | .session-bg { 2 | background-color: transparentize($color: $layer0, $amount: 0.4); 3 | } 4 | 5 | .session-button { 6 | @include large-rounding; 7 | min-width: 8.182rem; 8 | min-height: 8.182rem; 9 | background-color: $layer1; 10 | color: $onLayer1; 11 | font-size: 3rem; 12 | } 13 | 14 | .session-button-focused { 15 | background-color: $layer1Hover; 16 | } 17 | 18 | .session-button-desc { 19 | background-color: $layer2; 20 | color: $onLayer2; 21 | border-bottom-left-radius: $rounding_large; 22 | border-bottom-right-radius: $rounding_large; 23 | padding: 0.205rem 0.341rem; 24 | font-weight: 700; 25 | } 26 | 27 | .session-button-cancel { 28 | @include large-rounding; 29 | min-width: 8.182rem; 30 | min-height: 5.455rem; 31 | background-color: $layer1; 32 | color: $onLayer1; 33 | font-size: 3rem; 34 | } 35 | 36 | @for $i from 1 through 7 { 37 | .session-color-#{$i} { 38 | color: nth($sessionColors, $i); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/share/sleex/scss/_wal.scss: -------------------------------------------------------------------------------- 1 | // To prevent errors 2 | $color1: $surfaceVariant; 3 | $color2: $surfaceVariant; 4 | $color3: $surfaceVariant; 5 | $color4: $secondaryContainer; 6 | $color5: $secondaryContainer; 7 | $color6: $secondaryContainer; 8 | $color7: $onBackground; -------------------------------------------------------------------------------- /src/share/sleex/scss/_wallpaper.scss: -------------------------------------------------------------------------------- 1 | .wallpaper-list { 2 | .preview-box { 3 | min-width: 150px; 4 | min-height: 90px; 5 | background-size: cover; 6 | background-position: center; 7 | border-radius: 8px; 8 | } 9 | 10 | button { 11 | padding: 4px; 12 | margin: 4px; 13 | } 14 | 15 | .scroll-box { 16 | min-height: 110px; 17 | } 18 | } 19 | 20 | .wallpaper-window { 21 | @extend .dashboard; 22 | } 23 | 24 | .wallpaper-placeholder { 25 | padding: 2rem; 26 | 27 | .txt-large { 28 | font-size: 1.2em; 29 | } 30 | 31 | .txt-subtext { 32 | opacity: 0.8; 33 | } 34 | } 35 | 36 | .generate-thumbnails { 37 | padding: 0.5rem 1rem; 38 | border-radius: 9999px; 39 | background-color: $secondaryContainer; 40 | color: $onSecondaryContainer; 41 | margin-right: 0.5rem; 42 | 43 | &:hover { 44 | background-color: mix($secondaryContainer, $onSecondaryContainer, 90%); 45 | } 46 | 47 | &:active { 48 | background-color: mix($secondaryContainer, $onSecondaryContainer, 80%); 49 | } 50 | } 51 | 52 | .wallselect { 53 | background-color: $layer0; 54 | @include normal-rounding; 55 | padding: 1rem; 56 | } -------------------------------------------------------------------------------- /src/share/sleex/scss/fallback/_material.scss: -------------------------------------------------------------------------------- 1 | $darkmode: True; 2 | $transparent: False; 3 | $glass: #ffffff1a; 4 | $primary_paletteKeyColor: #192830; 5 | $secondary_paletteKeyColor: #4D616C; 6 | $tertiary_paletteKeyColor: #5F5A7D; 7 | $neutral_paletteKeyColor: #6D797D; 8 | $neutral_variant_paletteKeyColor: #6A7A7F; 9 | $background: #0F1417; 10 | $onBackground: #DFE3E7; 11 | $surface: #0F1417; 12 | $surfaceDim: #0F1417; 13 | $surfaceBright: #353A3D; 14 | $surfaceContainerLowest: #0A0F12; 15 | $surfaceContainerLow: #171C1F; 16 | $surfaceContainer: #1B2023; 17 | $surfaceContainerHigh: #262B2E; 18 | $surfaceContainerHighest: #313539; 19 | $onSurface: #DFE3E7; 20 | $surfaceVariant: #40484C; 21 | $onSurfaceVariant: #C0C7CD; 22 | $inverseSurface: #DFE3E7; 23 | $inverseOnSurface: #2C3134; 24 | $outline: #8A9297; 25 | $outlineVariant: #40484C; 26 | $shadow: #000000; 27 | $scrim: #000000; 28 | $surfaceTint: #8DCFF2; 29 | $primary: #8DCFF2; 30 | $onPrimary: #003548; 31 | $primaryContainer: #004D67; 32 | $onPrimaryContainer: #C1E8FF; 33 | $inversePrimary: #186584; 34 | $secondary: #B5CAD7; 35 | $onSecondary: #1F333D; 36 | $secondaryContainer: #364954; 37 | $onSecondaryContainer: #D1E6F3; 38 | $tertiary: #C8C2EA; 39 | $onTertiary: #302C4C; 40 | $tertiaryContainer: #474364; 41 | $onTertiaryContainer: #E5DEFF; 42 | $error: #FFB4AB; 43 | $onError: #690005; 44 | $errorContainer: #93000A; 45 | $onErrorContainer: #FFDAD6; 46 | $primaryFixed: #C1E8FF; 47 | $primaryFixedDim: #8DCFF2; 48 | $onPrimaryFixed: #001E2B; 49 | $onPrimaryFixedVariant: #004D67; 50 | $secondaryFixed: #D1E6F3; 51 | $secondaryFixedDim: #B5CAD7; 52 | $onSecondaryFixed: #091E27; 53 | $onSecondaryFixedVariant: #364954; 54 | $tertiaryFixed: #E5DEFF; 55 | $tertiaryFixedDim: #C8C2EA; 56 | $onTertiaryFixed: #1B1736; 57 | $onTertiaryFixedVariant: #474364; 58 | -------------------------------------------------------------------------------- /src/share/sleex/scss/main.scss: -------------------------------------------------------------------------------- 1 | // Reset 2 | // * { 3 | // all: unset; 4 | // } 5 | *:not(popover) { all: unset; } 6 | 7 | // Colors 8 | @import 'material'; // Material colors 9 | @import './colors'; // Global color definitions. Uses material colors as base. 10 | @import './lib_mixins'; 11 | @import 'lib_mixins_overrides'; 12 | @import './lib_classes'; 13 | @import './common'; // Context menu n stuff 14 | 15 | // Components 16 | @import './bar'; 17 | @import './cheatsheet'; 18 | @import './desktopbackground'; 19 | @import './osd'; 20 | @import './overview'; 21 | @import './sidebars'; 22 | @import './session'; 23 | @import './notifications'; 24 | @import './wallpaper'; 25 | 26 | // Music is put last as it might mess stuff up with pywal 27 | @import './music'; // Everything related to music is here 28 | 29 | // Classes for interaction 30 | .growingRadial { 31 | transition: 300ms cubic-bezier(0.2, 0.0, 0, 1.0); 32 | } 33 | .fadingRadial { 34 | transition: 50ms cubic-bezier(0.2, 0.0, 0, 1.0); 35 | } 36 | .sidebar-pinned { 37 | margin: 0rem; 38 | border-radius: 0rem; 39 | border-bottom-right-radius: $rounding_large; 40 | border: 0rem solid; 41 | } 42 | -------------------------------------------------------------------------------- /src/share/sleex/services/darkmode.js: -------------------------------------------------------------------------------- 1 | const { Gio, GLib } = imports.gi; 2 | import Service from 'resource:///com/github/Aylur/ags/service.js'; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 4 | import { darkMode } from '../modules/.miscutils/system.js'; 5 | const { exec, execAsync } = Utils; 6 | 7 | const timeBefore = (time1, time2) => { // Arrays of [hour, minute] 8 | if (time1[0] == time2[0]) return time1[1] < time2[1]; 9 | return time1[0] < time2[0]; 10 | } 11 | 12 | const timeSame = (time1, time2) => // Arrays of [hour, minute] 13 | (time1[0] == time2[0] && time1[1] == time2[1]); 14 | 15 | const timeBeforeOrSame = (time1, time2) => // Arrays of [hour, minute] 16 | (timeBefore(time1, time2) || timeSame(time1, time2)); 17 | 18 | const timeInRange = (time, rangeStart, rangeEnd) => { // Arrays of [hour, minute] 19 | if (timeBefore(rangeStart, rangeEnd)) 20 | return (timeBeforeOrSame(rangeStart, time) && timeBeforeOrSame(time, rangeEnd)) 21 | else { // rangeEnd < rangeStart, meaning it ends the following day 22 | rangeEnd[0] += 24; 23 | if (timeBefore(time, rangeStart)) time[0] += 24; 24 | return (timeBeforeOrSame(rangeStart, time) && timeBeforeOrSame(time, rangeEnd)) 25 | } 26 | 27 | } 28 | 29 | export async function startAutoDarkModeService() { 30 | Utils.interval(userOptions.time.interval, () => { 31 | if ((!userOptions.appearance.autoDarkMode.enabled)) return; 32 | const fromTime = (userOptions.appearance.autoDarkMode.from).split(':').map(Number); 33 | const toTime = (userOptions.appearance.autoDarkMode.to).split(':').map(Number); 34 | if (fromTime == toTime) return; 35 | const currentDateTime = GLib.DateTime.new_now_local(); 36 | const currentTime = [currentDateTime.get_hour(), currentDateTime.get_minute()]; 37 | darkMode.value = timeInRange(currentTime, fromTime, toTime); 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /src/share/sleex/services/globalinfo.js: -------------------------------------------------------------------------------- 1 | const { Gio, GLib } = imports.gi; 2 | import Service from 'resource:///com/github/Aylur/ags/service.js'; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 4 | const { exec, execAsync } = Utils; 5 | 6 | class CheatService extends Service { 7 | static { 8 | Service.register( 9 | this, 10 | { 'updated': [], }, 11 | ); 12 | } 13 | _cheatPath = ''; 14 | _cheatJson = []; 15 | 16 | refresh(value) { 17 | this.emit('updated', value); 18 | } 19 | 20 | connectWidget(widget, callback) { 21 | this.connect(widget, callback, 'updated'); 22 | } 23 | 24 | get todo_json() { 25 | return this._todoJson; 26 | } 27 | 28 | _save() { 29 | Utils.writeFile(JSON.stringify(this._cheatJson), this._cheatPath) 30 | .catch(print); 31 | } 32 | 33 | add(content) { 34 | this._cheatJson.push({ content, done: false }); 35 | this._save(); 36 | this.emit('updated'); 37 | } 38 | 39 | check(index) { 40 | this._cheatJson[index].done = true; 41 | this._save(); 42 | this.emit('updated'); 43 | } 44 | 45 | uncheck(index) { 46 | this._cheatJson[index].done = false; 47 | this._save(); 48 | this.emit('updated'); 49 | } 50 | 51 | remove(index) { 52 | this._cheatJson.splice(index, 1); 53 | Utils.writeFile(JSON.stringify(this._cheatJson), this._cheatPath) 54 | .catch(print); 55 | this.emit('updated'); 56 | } 57 | 58 | constructor() { 59 | super(); 60 | this._cheatPath = `${GLib.get_user_state_dir()}/ags/user/cheat.json`; 61 | try { 62 | const fileContents = Utils.readFile(this._cheatPath); 63 | this._cheatJson = JSON.parse(fileContents); 64 | } 65 | catch { 66 | Utils.exec(`bash -c 'mkdir -p ${GLib.get_user_cache_dir()}/ags/user'`); 67 | Utils.exec(`touch ${this._cheatPath}`); 68 | Utils.writeFile("[]", this._cheatPath).then(() => { 69 | this._cheatJson = JSON.parse(Utils.readFile(this._cheatPath)) 70 | }).catch(print); 71 | } 72 | } 73 | } 74 | 75 | // Singleton instance 76 | const service = new CheatService(); 77 | 78 | // make it global for easy use with cli 79 | globalThis.cheatService = service; 80 | 81 | export default service; -------------------------------------------------------------------------------- /src/share/sleex/services/indicator.js: -------------------------------------------------------------------------------- 1 | import Service from 'resource:///com/github/Aylur/ags/service.js'; 2 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 3 | 4 | class IndicatorService extends Service { 5 | static { 6 | Service.register( 7 | this, 8 | { 'popup': ['double'], }, 9 | ); 10 | } 11 | 12 | _delay = 1500; 13 | _count = 0; 14 | 15 | popup(value) { 16 | this.emit('popup', value); 17 | this._count++; 18 | Utils.timeout(this._delay, () => { 19 | this._count--; 20 | 21 | if (this._count === 0) 22 | this.emit('popup', -1); 23 | }); 24 | } 25 | 26 | connectWidget(widget, callback) { 27 | connect(this, widget, callback, 'popup'); 28 | } 29 | } 30 | 31 | // the singleton instance 32 | const service = new IndicatorService(); 33 | 34 | // make it global for easy use with cli 35 | globalThis['indicator'] = service; 36 | 37 | // export to use in other modules 38 | export default service; -------------------------------------------------------------------------------- /src/share/sleex/services/lockscreen.js: -------------------------------------------------------------------------------- 1 | import Service from 'resource:///com/github/Aylur/ags/service.js'; 2 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 3 | import App from 'resource:///com/github/Aylur/ags/app.js'; 4 | const authpy = App.configDir + '/modules/lockscreen/auth.py'; 5 | 6 | class Lockscreen extends Service { 7 | static { 8 | Service.register(this, { 9 | 'lock': ['boolean'], 10 | 'authenticating': ['boolean'], 11 | }); 12 | } 13 | 14 | lockscreen() { this.emit('lock', true); } 15 | 16 | /** @param {string} password */ 17 | auth(password) { 18 | this.emit('authenticating', true); 19 | Utils.execAsync([authpy, password]) 20 | .then(out => { 21 | this.emit('lock', out !== 'True'); 22 | this.emit('authenticating', false); 23 | }) 24 | .catch(err => console.error(err)); 25 | } 26 | } 27 | 28 | export default new Lockscreen(); -------------------------------------------------------------------------------- /src/share/sleex/services/messages.js: -------------------------------------------------------------------------------- 1 | const { Notify, GLib, Gio } = imports.gi; 2 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 3 | import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; 4 | 5 | export function fileExists(filePath) { 6 | let file = Gio.File.new_for_path(filePath); 7 | return file.query_exists(null); 8 | } 9 | 10 | const FIRST_RUN_FILE = "firstrun.txt"; 11 | const FIRST_RUN_PATH = `${GLib.get_user_state_dir()}/ags/user/${FIRST_RUN_FILE}`; 12 | const FIRST_RUN_FILE_CONTENT = "Just a file to confirm that you have been greeted ;)"; 13 | const APP_NAME = "AxOS"; 14 | const FIRST_RUN_NOTIF_TITLE = "Welcome!"; 15 | const FIRST_RUN_NOTIF_BODY = `First run? 👀 CTRL+SUPER+T to pick a wallpaper (or styles will break!)\nFor a list of keybinds, hit Super + F1.`; 16 | 17 | var batteryWarned = false; 18 | async function batteryMessage() { 19 | const perc = Battery.percent; 20 | const charging = Battery.charging; 21 | if (charging) { 22 | batteryWarned = false; 23 | return; 24 | } 25 | for (let i = userOptions.battery.warnLevels.length - 1; i >= 0; i--) { 26 | if (perc <= userOptions.battery.warnLevels[i] && !charging && !batteryWarned) { 27 | batteryWarned = true; 28 | Utils.execAsync(['bash', '-c', 29 | `notify-send "${userOptions.battery.warnTitles[i]}" "${userOptions.battery.warnMessages[i]}" -u critical -a '${APP_NAME}' -t 69420 &` 30 | ]).catch(print); 31 | break; 32 | } 33 | } 34 | if (perc <= userOptions.battery.suspendThreshold) { 35 | Utils.execAsync(['bash', '-c', 36 | `notify-send "Suspending system" "Critical battery level (${perc}% remaining)" -u critical -a '${APP_NAME}' -t 69420 &` 37 | ]).catch(print); 38 | Utils.execAsync('systemctl suspend').catch(print); 39 | } 40 | } 41 | 42 | export async function startBatteryWarningService() { 43 | Utils.timeout(1, () => { 44 | Battery.connect('changed', () => batteryMessage().catch(print)); 45 | }) 46 | } 47 | 48 | export async function firstRunWelcome() { 49 | GLib.mkdir_with_parents(`${GLib.get_user_state_dir()}/ags/user`, 755); 50 | if (!fileExists(FIRST_RUN_PATH)) { 51 | Utils.writeFile(FIRST_RUN_FILE_CONTENT, FIRST_RUN_PATH) 52 | .then(() => { 53 | // Note that we add a little delay to make sure the cool circular progress works 54 | Utils.execAsync(['hyprctl', 'keyword', 'bind', "Super,Slash,exec,ags -t cheatsheet"]).catch(print); 55 | Utils.execAsync(['bash', '-c', `sleep 0.5; notify-send "Millis since epoch" "$(date +%s%N | cut -b1-13)"; sleep 0.5; notify-send '${FIRST_RUN_NOTIF_TITLE}' '${FIRST_RUN_NOTIF_BODY}' -a '${APP_NAME}' &` ]).catch(print) 56 | Utils.execAsync(['bash', '-c', `sh /usr/share/sleex/scripts/color_generation/switchwall.sh --path /usr/share/sleex/wallpapers/sakura.png`, '&']).catch(print); 57 | }) 58 | .catch(print); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/share/sleex/services/todo.js: -------------------------------------------------------------------------------- 1 | const { Gio, GLib } = imports.gi; 2 | import Service from 'resource:///com/github/Aylur/ags/service.js'; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 4 | const { exec, execAsync } = Utils; 5 | 6 | class TodoService extends Service { 7 | static { 8 | Service.register( 9 | this, 10 | { 'updated': [], }, 11 | ); 12 | } 13 | 14 | _todoPath = ''; 15 | _todoJson = []; 16 | 17 | refresh(value) { 18 | this.emit('updated', value); 19 | } 20 | 21 | connectWidget(widget, callback) { 22 | this.connect(widget, callback, 'updated'); 23 | } 24 | 25 | get todo_json() { 26 | return this._todoJson; 27 | } 28 | 29 | _save() { 30 | Utils.writeFile(JSON.stringify(this._todoJson), this._todoPath) 31 | .catch(print); 32 | } 33 | 34 | add(content) { 35 | this._todoJson.push({ content, done: false }); 36 | this._save(); 37 | this.emit('updated'); 38 | } 39 | 40 | check(index) { 41 | this._todoJson[index].done = true; 42 | this._save(); 43 | this.emit('updated'); 44 | } 45 | 46 | uncheck(index) { 47 | this._todoJson[index].done = false; 48 | this._save(); 49 | this.emit('updated'); 50 | } 51 | 52 | remove(index) { 53 | this._todoJson.splice(index, 1); 54 | Utils.writeFile(JSON.stringify(this._todoJson), this._todoPath) 55 | .catch(print); 56 | this.emit('updated'); 57 | } 58 | 59 | constructor() { 60 | super(); 61 | this._todoPath = `${GLib.get_user_state_dir()}/ags/user/todo.json`; 62 | try { 63 | const fileContents = Utils.readFile(this._todoPath); 64 | this._todoJson = JSON.parse(fileContents); 65 | } 66 | catch { 67 | Utils.exec(`bash -c 'mkdir -p ${GLib.get_user_cache_dir()}/ags/user'`); 68 | Utils.exec(`touch ${this._todoPath}`); 69 | Utils.writeFile("[]", this._todoPath).then(() => { 70 | this._todoJson = JSON.parse(Utils.readFile(this._todoPath)) 71 | }).catch(print); 72 | } 73 | } 74 | } 75 | 76 | // the singleton instance 77 | const service = new TodoService(); 78 | 79 | // make it global for easy use with cli 80 | globalThis.todo = service; 81 | 82 | // export to use in other modules 83 | export default service; -------------------------------------------------------------------------------- /src/share/sleex/services/wallpaper.js: -------------------------------------------------------------------------------- 1 | const { Gdk, GLib } = imports.gi; 2 | import Service from 'resource:///com/github/Aylur/ags/service.js'; 3 | import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; 4 | 5 | const WALLPAPER_CONFIG_PATH = `${GLib.get_user_state_dir()}/ags/user/wallpaper.json`; 6 | 7 | class WallpaperService extends Service { 8 | static { 9 | Service.register( 10 | this, 11 | { 'updated': [], }, 12 | ); 13 | } 14 | 15 | _wallPath = ''; 16 | _wallJson = []; 17 | _monitorCount = 1; 18 | 19 | _save() { 20 | Utils.writeFile(JSON.stringify(this._wallJson), this._wallPath) 21 | .catch(print); 22 | } 23 | 24 | add(path) { 25 | this._wallJson.push(path); 26 | this._save(); 27 | this.emit('updated'); 28 | } 29 | 30 | set(path, monitor = -1) { 31 | this._monitorCount = Gdk.Display.get_default()?.get_n_monitors() || 1; 32 | if (this._wallJson.length < this._monitorCount) this._wallJson[this._monitorCount - 1] = ""; 33 | if (monitor == -1) 34 | this._wallJson.fill(path); 35 | else 36 | this._wallJson[monitor] = path; 37 | 38 | this._save(); 39 | this.emit('updated'); 40 | } 41 | 42 | get(monitor = 0) { 43 | return this._wallJson[monitor]; 44 | } 45 | 46 | constructor() { 47 | super(); 48 | // How many screens? 49 | this._monitorCount = Gdk.Display.get_default()?.get_n_monitors() || 1; 50 | // Read config 51 | this._wallPath = WALLPAPER_CONFIG_PATH; 52 | try { 53 | const fileContents = Utils.readFile(this._wallPath); 54 | this._wallJson = JSON.parse(fileContents); 55 | } 56 | catch { 57 | Utils.exec(`bash -c 'mkdir -p ${GLib.get_user_cache_dir()}/ags/user'`); 58 | Utils.exec(`touch ${this._wallPath}`); 59 | Utils.writeFile('[]', this._wallPath).then(() => { 60 | this._wallJson = JSON.parse(Utils.readFile(this._wallPath)) 61 | }).catch(print); 62 | } 63 | } 64 | } 65 | 66 | // instance 67 | const service = new WallpaperService(); 68 | // make it global for easy use with cli 69 | globalThis['wallpaper'] = service; 70 | export default service; -------------------------------------------------------------------------------- /src/share/sleex/services/weather.js: -------------------------------------------------------------------------------- 1 | // This is for the right pills of the bar. 2 | import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; 3 | const { execAsync } = Utils; 4 | const { GLib } = imports.gi; 5 | 6 | const WEATHER_CACHE_FOLDER = `${GLib.get_user_cache_dir()}/ags/weather`; 7 | Utils.exec(`mkdir -p ${WEATHER_CACHE_FOLDER}`); 8 | 9 | Utils.interval(900000, async () => { 10 | const WEATHER_CACHE_PATH = WEATHER_CACHE_FOLDER + "/wttr.in.txt"; 11 | const updateWeatherForCity = (city) => 12 | execAsync(`curl https://wttr.in/${city.replace(/ /g, "%20")}?format=j1`) 13 | .then((output) => { 14 | const weather = JSON.parse(output); 15 | Utils.writeFile(JSON.stringify(weather),WEATHER_CACHE_PATH).catch(print); 16 | }).catch(print); 17 | 18 | if (userOptions.weather.city != "" && userOptions.weather.city != null) { 19 | updateWeatherForCity(userOptions.weather.city.replace(/ /g, "%20")); 20 | } else { 21 | Utils.execAsync("curl ipinfo.io") 22 | .then((output) => { 23 | return JSON.parse(output)["city"].toLowerCase(); 24 | }) 25 | .then(updateWeatherForCity) 26 | .catch(print); 27 | } 28 | }); -------------------------------------------------------------------------------- /src/share/sleex/user_options.js: -------------------------------------------------------------------------------- 1 | const userConfigOptions = { 2 | } 3 | 4 | export default userConfigOptions; 5 | -------------------------------------------------------------------------------- /src/share/sleex/variables.js: -------------------------------------------------------------------------------- 1 | const { Gdk, Gtk } = imports.gi; 2 | import App from 'resource:///com/github/Aylur/ags/app.js' 3 | import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; 4 | import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; 5 | import Variable from 'resource:///com/github/Aylur/ags/variable.js'; 6 | 7 | Gtk.IconTheme.get_default().append_search_path(`${App.configDir}/assets/icons`); 8 | 9 | // Global vars for external control (through keybinds) 10 | export const showMusicControls = Variable(false, {}) 11 | export const showColorScheme = Variable(false, {}) 12 | globalThis['openMusicControls'] = showMusicControls; 13 | globalThis['openColorScheme'] = showColorScheme; 14 | globalThis['mpris'] = Mpris; 15 | 16 | // load monitor shell modes from userOptions 17 | const initialMonitorShellModes = () => { 18 | const numberOfMonitors = Gdk.Display.get_default()?.get_n_monitors() || 1; 19 | const monitorBarConfigs = []; 20 | for (let i = 0; i < numberOfMonitors; i++) { 21 | if (userOptions.bar.modes[i]) { 22 | monitorBarConfigs.push(userOptions.bar.modes[i]) 23 | } else { 24 | monitorBarConfigs.push('normal') 25 | } 26 | } 27 | return monitorBarConfigs; 28 | 29 | } 30 | export const currentShellMode = Variable(initialMonitorShellModes(), {}) // normal, focus 31 | 32 | // Mode switching 33 | const updateMonitorShellMode = (monitorShellModes, monitor, mode) => { 34 | const newValue = [...monitorShellModes.value]; 35 | newValue[monitor] = mode; 36 | monitorShellModes.value = newValue; 37 | } 38 | globalThis['currentMode'] = currentShellMode; 39 | globalThis['cycleMode'] = () => { 40 | const monitor = Hyprland.active.monitor.id || 0; 41 | 42 | if (currentShellMode.value[monitor] === 'normal') { 43 | updateMonitorShellMode(currentShellMode, monitor, 'focus') 44 | } 45 | else if (currentShellMode.value[monitor] === 'focus') { 46 | updateMonitorShellMode(currentShellMode, monitor, 'nothing') 47 | } 48 | else { 49 | updateMonitorShellMode(currentShellMode, monitor, 'normal') 50 | } 51 | } 52 | 53 | // Window controls 54 | const range = (length, start = 1) => Array.from({ length }, (_, i) => i + start); 55 | globalThis['toggleWindowOnAllMonitors'] = (name) => { 56 | range(Gdk.Display.get_default()?.get_n_monitors() || 1, 0).forEach(id => { 57 | App.toggleWindow(`${name}${id}`); 58 | }); 59 | } 60 | globalThis['closeWindowOnAllMonitors'] = (name) => { 61 | range(Gdk.Display.get_default()?.get_n_monitors() || 1, 0).forEach(id => { 62 | App.closeWindow(`${name}${id}`); 63 | }); 64 | } 65 | globalThis['openWindowOnAllMonitors'] = (name) => { 66 | range(Gdk.Display.get_default()?.get_n_monitors() || 1, 0).forEach(id => { 67 | App.openWindow(`${name}${id}`); 68 | }); 69 | } 70 | 71 | globalThis['closeEverything'] = () => { 72 | const numMonitors = Gdk.Display.get_default()?.get_n_monitors() || 1; 73 | for (let i = 0; i < numMonitors; i++) { 74 | App.closeWindow(`cheatsheet${i}`); 75 | App.closeWindow(`session${i}`); 76 | } 77 | App.closeWindow('sideleft'); 78 | App.closeWindow('dashboard'); 79 | App.closeWindow('overview'); 80 | }; 81 | -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/aesthetic_deer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/aesthetic_deer.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/apple-light.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/apple-light.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/building_cyber.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/building_cyber.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/city-rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/city-rain.png -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/city-skyline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/city-skyline.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/city.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/city.gif -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/deer_and_sunset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/deer_and_sunset.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/earth-from-moon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/earth-from-moon.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/escape_velocity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/escape_velocity.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/evening-landscape.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/evening-landscape.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/explorer_green_day.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/explorer_green_day.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/explorer_orange_sunset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/explorer_orange_sunset.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/highlands-grid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/highlands-grid.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/landscape-abstract-neon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/landscape-abstract-neon.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/lofoten-sundown.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/lofoten-sundown.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/lofoten2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/lofoten2.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/loupe-mono-dark-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/loupe-mono-dark-preview.png -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/midnight-reflections-moonlit-sea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/midnight-reflections-moonlit-sea.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/moonlight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/moonlight.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/mountain-lake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/mountain-lake.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/mountain-sunrise.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/mountain-sunrise.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/mountain-winter1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/mountain-winter1.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/mountain-winter3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/mountain-winter3.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/mountain_view.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/mountain_view.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/nordwall3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/nordwall3.jpg -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/oldhouse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/oldhouse.gif -------------------------------------------------------------------------------- /src/share/sleex/wallpapers/sakura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AxOS-project/Sleex/79c902686994cd0359702d41de09ed622c101b00/src/share/sleex/wallpapers/sakura.png -------------------------------------------------------------------------------- /src/share/wayland-sessions/sleex.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Sleex 3 | Comment=AxOS's third desktop environment 4 | Exec=sleex 5 | Icon= 6 | Type=Application --------------------------------------------------------------------------------