aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorDonald Williams <129223418+dwilliam62@users.noreply.github.com>2025-10-13 20:31:53 -0400
committerGitHub <noreply@github.com>2025-10-13 20:31:53 -0400
commite4be12e23fa8d6f8a73dde974ea6adf242885bc1 (patch)
treeb879abcf54989120a0931443bfb8203c885c2b20 /config
parent0e52d19b894e3cfd2c87cfbcc35ae087d48f5485 (diff)
parent9d26c191c1071a542e816d1bc2b0b3f96ebfa74d (diff)
Merge pull request #841 from JaKooLit/ddubs-hyprsunset
Merge ddubs-hyprsunset into main fixes for wallust, sddm and weather
Diffstat (limited to 'config')
-rw-r--r--config/hypr/UserConfigs/Startup_Apps.conf4
-rw-r--r--config/hypr/UserConfigs/UserKeybinds.conf5
-rw-r--r--config/hypr/UserConfigs/UserSettings.conf1
-rw-r--r--config/hypr/UserConfigs/WindowRules.conf1
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperEffects.sh58
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperSelect.sh22
-rwxr-xr-xconfig/hypr/UserScripts/Weather.py591
-rwxr-xr-xconfig/hypr/scripts/Hyprsunset.sh99
-rwxr-xr-xconfig/hypr/scripts/MediaCtrl.sh65
-rw-r--r--config/hypr/scripts/sddm_wallpaper.sh23
-rw-r--r--config/hypr/v2.3.165
-rw-r--r--config/quickshell/modules/common/ConfigOptions.qml1
-rw-r--r--config/quickshell/modules/overview/Overview.qml2
-rw-r--r--config/quickshell/modules/overview/OverviewWidget.qml40
-rw-r--r--config/quickshell/modules/overview/OverviewWindow.qml27
-rw-r--r--config/waybar/ModulesCustom13
-rw-r--r--config/waybar/ModulesGroups2
-rw-r--r--config/waybar/configs/[BOT & Left] SouthWest1
-rw-r--r--config/waybar/configs/[BOT & Right] SouthEast1
-rw-r--r--config/waybar/configs/[LEFT] WestWing1
-rw-r--r--config/waybar/configs/[LEFT] WestWing v21
-rw-r--r--config/waybar/configs/[RIGHT] EastWing1
-rw-r--r--config/waybar/configs/[RIGHT] EastWing v21
-rw-r--r--config/waybar/configs/[TOP & BOT] SummitSplit2
-rw-r--r--config/waybar/configs/[TOP & BOT] SummitSplit v23
-rw-r--r--config/waybar/configs/[TOP] 0-Ja-01
-rw-r--r--config/waybar/configs/[TOP] Arrow3
-rw-r--r--config/waybar/configs/[TOP] Camellia3
-rw-r--r--config/waybar/configs/[TOP] Chrysanthemum3
-rw-r--r--config/waybar/configs/[TOP] Default Laptop1
-rw-r--r--config/waybar/configs/[TOP] Everforest1
-rw-r--r--config/waybar/configs/[TOP] Gardenia3
-rw-r--r--config/waybar/configs/[TOP] Minimal - Long1
-rw-r--r--config/waybar/configs/[TOP] Minimal - Short1
-rw-r--r--config/waybar/configs/[TOP] Peony3
-rw-r--r--config/waybar/configs/[TOP] Sleek1
36 files changed, 318 insertions, 673 deletions
diff --git a/config/hypr/UserConfigs/Startup_Apps.conf b/config/hypr/UserConfigs/Startup_Apps.conf
index f8af55e4..7b668b77 100644
--- a/config/hypr/UserConfigs/Startup_Apps.conf
+++ b/config/hypr/UserConfigs/Startup_Apps.conf
@@ -20,6 +20,10 @@ exec-once = swww-daemon --format xrgb
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
+# Initialize Drop Down terminal - See Bug#810 https://github.com/JaKooLit/Hyprland-Dots/issues/810#issuecomment-3351947644
+exec-once = $HOME/.config/hypr/scripts/Dropterminal.sh kitty &
+
+
# Polkit (Polkit Gnome / KDE)
exec-once = $scriptsDir/Polkit.sh
diff --git a/config/hypr/UserConfigs/UserKeybinds.conf b/config/hypr/UserConfigs/UserKeybinds.conf
index 2f0e808f..4d35a9c9 100644
--- a/config/hypr/UserConfigs/UserKeybinds.conf
+++ b/config/hypr/UserConfigs/UserKeybinds.conf
@@ -29,6 +29,7 @@ bind = $mainMod, H, exec, $scriptsDir/KeyHints.sh # help / cheat sheet
bind = $mainMod ALT, R, exec, $scriptsDir/Refresh.sh # Refresh waybar, swaync, rofi
bind = $mainMod ALT, E, exec, $scriptsDir/RofiEmoji.sh # emoji menu
bind = $mainMod, S, exec, $scriptsDir/RofiSearch.sh # Google search using rofi
+bind = $mainMod SHIFT, S, exec, rofi -show windows # list/switch apps using rofi
bind = $mainMod ALT, O, exec, $scriptsDir/ChangeBlur.sh # Toggle blur settings
bind = $mainMod SHIFT, G, exec, $scriptsDir/GameMode.sh # Toggle animations ON/OFF
bind = $mainMod ALT, L, exec, $scriptsDir/ChangeLayout.sh # Toggle Master or Dwindle Layout
@@ -55,6 +56,9 @@ bind = $mainMod CTRL ALT, B, exec, pkill -SIGUSR1 waybar # Toggle hide/show wayb
bind = $mainMod CTRL, B, exec, $scriptsDir/WaybarStyles.sh # Waybar Styles Menu
bind = $mainMod ALT, B, exec, $scriptsDir/WaybarLayout.sh # Waybar Layout Menu
+# Night light toggle (Hyprsunset)
+bind = $mainMod, N, exec, $scriptsDir/Hyprsunset.sh toggle
+
# FEATURES / EXTRAS (UserScripts)
bind = $mainMod SHIFT, M, exec, $UserScripts/RofiBeats.sh # online music using rofi
bind = $mainMod, W, exec, $UserScripts/WallpaperSelect.sh # Select wallpaper to apply
@@ -74,6 +78,7 @@ bind = $mainMod CTRL, F10, movecurrentworkspacetomonitor, r #move current worksp
bind = $mainMod CTRL, F11, movecurrentworkspacetomonitor, u #move current workspace to UP monitor
bind = $mainMod CTRL, F12, movecurrentworkspacetomonitor, d #move current workspace to DOWN monitor
+
# For passthrough keyboard into a VM
# bind = $mainMod ALT, P, submap, passthru
#submap = passthru
diff --git a/config/hypr/UserConfigs/UserSettings.conf b/config/hypr/UserConfigs/UserSettings.conf
index 325d24f7..f81ccc6a 100644
--- a/config/hypr/UserConfigs/UserSettings.conf
+++ b/config/hypr/UserConfigs/UserSettings.conf
@@ -63,6 +63,7 @@ input {
}
}
+
gestures {
gesture = 3, horizontal, workspace
workspace_swipe_distance = 500
diff --git a/config/hypr/UserConfigs/WindowRules.conf b/config/hypr/UserConfigs/WindowRules.conf
index 16dc48a5..d6959dc4 100644
--- a/config/hypr/UserConfigs/WindowRules.conf
+++ b/config/hypr/UserConfigs/WindowRules.conf
@@ -180,6 +180,7 @@ windowrule = opacity 0.8 0.7, class:^(gedit|org.gnome.TextEditor|mousepad)$
windowrule = opacity 0.9 0.8, class:^(deluge)$
windowrule = opacity 0.9 0.8, class:^(seahorse)$ # gnome-keyring gui
windowrule = opacity 0.95 0.75, title:^(Picture-in-Picture)$
+windowrule = opacity 0.9,class:^(code)$
# SIZE
windowrule = size 65% 90%, tag:KooL_Cheat*
diff --git a/config/hypr/UserScripts/WallpaperEffects.sh b/config/hypr/UserScripts/WallpaperEffects.sh
index 2ba58d0c..ac8fc0e8 100755
--- a/config/hypr/UserScripts/WallpaperEffects.sh
+++ b/config/hypr/UserScripts/WallpaperEffects.sh
@@ -108,31 +108,41 @@ main
sleep 1
if [[ -n "$choice" ]]; then
- sddm_simple="/usr/share/sddm/themes/simple_sddm_2"
- if [ -d "$sddm_simple" ]; then
-
- # Check if yad is running to avoid multiple yad notification
- if pidof yad > /dev/null; then
- killall yad
- fi
-
- if yad --info --text="Set current wallpaper as SDDM background?\n\nNOTE: This only applies to SIMPLE SDDM v2 Theme" \
- --text-align=left \
- --title="SDDM Background" \
- --timeout=5 \
- --timeout-indicator=right \
- --button="yad-yes:0" \
- --button="yad-no:1" \
- ; then
+ # Resolve SDDM themes directory (standard and NixOS path)
+ sddm_themes_dir=""
+ if [ -d "/usr/share/sddm/themes" ]; then
+ sddm_themes_dir="/usr/share/sddm/themes"
+ elif [ -d "/run/current-system/sw/share/sddm/themes" ]; then
+ sddm_themes_dir="/run/current-system/sw/share/sddm/themes"
+ fi
- # Check if terminal exists
- if ! command -v "$terminal" &>/dev/null; then
- notify-send -i "$iDIR/ja.png" "Missing $terminal" "Install $terminal to enable setting of wallpaper background"
- exit 1
- fi
+ if [ -n "$sddm_themes_dir" ]; then
+ sddm_simple="$sddm_themes_dir/simple_sddm_2"
+
+ # Only prompt if theme exists and its Backgrounds directory is writable
+ if [ -d "$sddm_simple" ] && [ -w "$sddm_simple/Backgrounds" ]; then
+ # Check if yad is running to avoid multiple yad notification
+ if pidof yad > /dev/null; then
+ killall yad
+ fi
- exec $SCRIPTSDIR/sddm_wallpaper.sh --effects
-
+ if yad --info --text="Set current wallpaper as SDDM background?\n\nNOTE: This only applies to SIMPLE SDDM v2 Theme" \
+ --text-align=left \
+ --title="SDDM Background" \
+ --timeout=5 \
+ --timeout-indicator=right \
+ --button="yad-yes:0" \
+ --button="yad-no:1" \
+ ; then
+
+ # Check if terminal exists
+ if ! command -v "$terminal" &>/dev/null; then
+ notify-send -i "$iDIR/ja.png" "Missing $terminal" "Install $terminal to enable setting of wallpaper background"
+ exit 1
+ fi
+
+ exec "$SCRIPTSDIR/sddm_wallpaper.sh" --effects
+ fi
fi
fi
-fi \ No newline at end of file
+fi
diff --git a/config/hypr/UserScripts/WallpaperSelect.sh b/config/hypr/UserScripts/WallpaperSelect.sh
index a08b53ce..466832ba 100755
--- a/config/hypr/UserScripts/WallpaperSelect.sh
+++ b/config/hypr/UserScripts/WallpaperSelect.sh
@@ -101,9 +101,21 @@ menu() {
# Offer SDDM Simple Wallpaper Option (only for non-video wallpapers)
set_sddm_wallpaper() {
sleep 1
- sddm_simple="/usr/share/sddm/themes/simple_sddm_2"
- if [ -d "$sddm_simple" ]; then
+ # Resolve SDDM themes directory (standard and NixOS path)
+ local sddm_themes_dir=""
+ if [ -d "/usr/share/sddm/themes" ]; then
+ sddm_themes_dir="/usr/share/sddm/themes"
+ elif [ -d "/run/current-system/sw/share/sddm/themes" ]; then
+ sddm_themes_dir="/run/current-system/sw/share/sddm/themes"
+ fi
+
+ [ -z "$sddm_themes_dir" ] && return 0
+
+ local sddm_simple="$sddm_themes_dir/simple_sddm_2"
+
+ # Only prompt if theme exists and its Backgrounds directory is writable
+ if [ -d "$sddm_simple" ] && [ -w "$sddm_simple/Backgrounds" ]; then
# Check if yad is running to avoid multiple notifications
if pidof yad >/dev/null; then
@@ -123,9 +135,9 @@ set_sddm_wallpaper() {
notify-send -i "$iDIR/error.png" "Missing $terminal" "Install $terminal to enable setting of wallpaper background"
exit 1
fi
-
- exec $SCRIPTSDIR/sddm_wallpaper.sh --normal
-
+
+ exec "$SCRIPTSDIR/sddm_wallpaper.sh" --normal
+
fi
fi
}
diff --git a/config/hypr/UserScripts/Weather.py b/config/hypr/UserScripts/Weather.py
index a71fe8ca..ca1d5281 100755
--- a/config/hypr/UserScripts/Weather.py
+++ b/config/hypr/UserScripts/Weather.py
@@ -9,7 +9,6 @@ import sys
import time
import html
from typing import Any, Dict, List, Optional, Tuple
-from datetime import datetime
import requests
@@ -18,7 +17,7 @@ import requests
# Examples (zsh):
# # One-off run
# # WEATHER_UNITS can be "metric" or "imperial"
-# WEATHER_UNITS=imperial WEATHER_PLACE="Concord, NH" python3 ~/.config/hypr/UserScripts/Weather.py
+# WEATHER_UNITS=imperial WEATHER_PLACE="Concord, NH" python3 /home/dwilliams/Projects/Weather.py
#
# # Persist in current shell session
# export WEATHER_UNITS=imperial
@@ -277,594 +276,6 @@ def fetch_open_meteo(lat: float, lon: float) -> Dict[str, Any]:
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_direction_10m,weather_code,visibility,precipitation,pressure_msl,is_day",
- "hourly": "precipitation_probability,weather_code",
- "daily": "temperature_2m_max,temperature_2m_min",
- "timezone": "auto",
- }
- params.update(units_params(UNITS))
- resp = SESSION.get(base, params=params, timeout=TIMEOUT)
- resp.raise_for_status()
- return resp.json()
-
-
-def fetch_aqi(lat: float, lon: float) -> Optional[Dict[str, Any]]:
- try:
- base = "https://air-quality-api.open-meteo.com/v1/air-quality"
- params = {
- "latitude": lat,
- "longitude": lon,
- "current": "european_aqi",
- "timezone": "auto",
- }
- resp = SESSION.get(base, params=params, timeout=TIMEOUT)
- resp.raise_for_status()
- return resp.json()
- except Exception as e:
- print(f"AQI fetch failed: {e}", file=sys.stderr)
- return None
-
-
-def fetch_place(lat: float, lon: float) -> Optional[str]:
- """Reverse geocode lat/lon to an approximate place. Tries Nominatim first, then Open-Meteo."""
- lang = os.getenv("WEATHER_LANG", "en")
-
- # 1) Nominatim (OpenStreetMap)
- try:
- base = "https://nominatim.openstreetmap.org/reverse"
- params = {
- "lat": lat,
- "lon": lon,
- "format": "jsonv2",
- "accept-language": lang,
- }
- headers = {"User-Agent": UA + " Weather.py/1.0"}
- resp = SESSION.get(base, params=params, headers=headers, timeout=TIMEOUT)
- resp.raise_for_status()
- data = resp.json()
- address = data.get("address", {})
- name = data.get("name") or address.get("city") or address.get("town") or address.get("village") or address.get("hamlet")
- admin1 = address.get("state")
- country = address.get("country")
- parts = [part for part in [name, admin1, country] if part]
- if parts:
- return ", ".join(parts)
- except Exception as e:
- log_debug(f"Reverse geocoding (Nominatim) failed: {e}")
-
- # 2) Open-Meteo reverse (fallback)
- try:
- base = "https://geocoding-api.open-meteo.com/v1/reverse"
- params = {
- "latitude": lat,
- "longitude": lon,
- "language": lang,
- "format": "json",
- }
- resp = SESSION.get(base, params=params, timeout=TIMEOUT)
- resp.raise_for_status()
- data = resp.json()
- results = data.get("results") or []
- if results:
- p = results[0]
- name = p.get("name")
- admin1 = p.get("admin1")
- country = p.get("country")
- parts = [part for part in [name, admin1, country] if part]
- if parts:
- return ", ".join(parts)
- except Exception as e:
- log_debug(f"Reverse geocoding (Open-Meteo) failed: {e}")
-
- return None
-
-
-# =============== Build Output ===============
-
-def safe_get(dct: Dict[str, Any], *keys, default=None):
- cur: Any = dct
- for k in keys:
- if isinstance(cur, dict):
- if k not in cur:
- return default
- cur = cur[k]
- elif isinstance(cur, list):
- try:
- cur = cur[k] # type: ignore[index]
- except Exception:
- return default
- else:
- return default
- return cur
-
-
-def build_hourly_precip(forecast: Dict[str, Any]) -> str:
- try:
- times: List[str] = safe_get(forecast, "hourly", "time", default=[]) or []
- probs: List[Optional[float]] = safe_get(
- forecast, "hourly", "precipitation_probability", default=[]
- ) or []
- cur_time: Optional[str] = safe_get(forecast, "current", "time")
- idx = times.index(cur_time) if cur_time in times else 0
- window = probs[idx : idx + 6]
- if not window:
- return ""
- parts = [f"{int(p)}%" if p is not None else "-" for p in window]
- return " (next 6h) " + " ".join(parts)
- except Exception:
- return ""
-
-
-def build_output(lat: float, lon: float, forecast: Dict[str, Any], aqi: Optional[Dict[str, Any]], place: Optional[str] = None) -> Tuple[Dict[str, Any], str]:
- cur = forecast.get("current", {})
- cur_units = forecast.get("current_units", {})
- daily = forecast.get("daily", {})
- daily_units = forecast.get("daily_units", {})
-
- temp_val = cur.get("temperature_2m")
- temp_unit = cur_units.get("temperature_2m", "")
- temp_str = f"{int(round(temp_val))}{temp_unit}" if isinstance(temp_val, (int, float)) else "N/A"
-
- feels_val = cur.get("apparent_temperature")
- feels_unit = cur_units.get("apparent_temperature", "")
- feels_str = f"Feels like {int(round(feels_val))}{feels_unit}" if isinstance(feels_val, (int, float)) else ""
-
- is_day = int(cur.get("is_day", 1) or 1)
- code = int(cur.get("weather_code", -1) or -1)
-
- unavailable = False
- if code == -1:
- try:
- times: List[str] = safe_get(forecast, "hourly", "time", default=[]) or []
- codes: List[Optional[int]] = safe_get(forecast, "hourly", "weather_code", default=[]) or []
- cur_time: Optional[str] = safe_get(forecast, "current", "time")
-
- idx = 0
- if cur_time and times:
- try:
- ct = datetime.fromisoformat(cur_time)
- diffs = []
- for t in times:
- try:
- diffs.append(abs((datetime.fromisoformat(t) - ct).total_seconds()))
- except Exception:
- diffs.append(float("inf"))
- idx = min(range(len(diffs)), key=lambda i: diffs[i]) if diffs else 0
- except Exception:
- idx = times.index(cur_time) if cur_time in times else 0
-
- hcode = None
- if isinstance(codes, list) and codes:
- if idx < len(codes) and isinstance(codes[idx], (int, float)):
- hcode = int(codes[idx])
- else:
- for c in codes:
- if isinstance(c, (int, float)):
- hcode = int(c)
- break
- if isinstance(hcode, int):
- code = hcode
- log_debug(f"Fallback hourly weather_code used: code={code} idx={idx} cur_time={cur_time}")
- except Exception as e:
- log_debug(f"Hourly code fallback failed: {e}")
-
- if not isinstance(code, int) or code < 0:
- unavailable = True
- log_debug("Weather code invalid; setting status to 'Condition Unavailable'")
-
- if unavailable:
- icon = WEATHER_ICONS["default"]
- status = "Condition Unavailable"
- code_for_class = "unavailable"
- else:
- icon = wmo_to_icon(code, is_day)
- status = wmo_to_status(code)
- code_for_class = f"wmo-{code} {'day' if is_day else 'night'}"
-
- # min/max today (index 0)
- tmin_val = safe_get(daily, "temperature_2m_min", 0)
- tmax_val = safe_get(daily, "temperature_2m_max", 0)
- dtemp_unit = daily_units.get("temperature_2m_min", temp_unit)
- tmin_str = f"{int(round(tmin_val))}{dtemp_unit}" if isinstance(tmin_val, (int, float)) else ""
- tmax_str = f"{int(round(tmax_val))}{dtemp_unit}" if isinstance(tmax_val, (int, float)) else ""
- min_max = f" {tmin_str}\t\t {tmax_str}" if tmin_str and tmax_str else ""
-
- wind_val = cur.get("wind_speed_10m")
- wind_unit = cur_units.get("wind_speed_10m", "")
- wind_text = f" {int(round(wind_val))}{wind_unit}" if isinstance(wind_val, (int, float)) else ""
-
- hum_val = cur.get("relative_humidity_2m")
- humidity_text = f" {int(hum_val)}%" if isinstance(hum_val, (int, float)) else ""
-
- vis_val = cur.get("visibility")
- visibility_text = f" {format_visibility(vis_val)}" if isinstance(vis_val, (int, float)) else ""
-
- aqi_val = safe_get(aqi or {}, "current", "european_aqi")
- aqi_text = f"AQI {int(aqi_val)}" if isinstance(aqi_val, (int, float)) else "AQI N/A"
-
- hourly_precip = build_hourly_precip(forecast)
- prediction = f"\n\n{hourly_precip}" if hourly_precip else ""
-
- # Build place string (priority: MANUAL_PLACE > ENV_PLACE > reverse geocode > lat,lon)
- place_str = (MANUAL_PLACE or ENV_PLACE or place or f"{lat:.3f}, {lon:.3f}")
- location_text = f"{LOC_ICON} {place_str}"
-
- # Build tooltip (markup or plain)
- if TOOLTIP_MARKUP:
- # Escape dynamic text to avoid breaking Pango markup
- tooltip_text = str.format(
- "\t\t{}\t\t\n{}\n{}\n{}\n{}\n\n{}\n{}\n{}{}",
- f'<span size="xx-large">{esc(temp_str)}</span>',
- f"<big> {icon}</big>",
- f"<b>{esc(status)}</b>",
- esc(location_text),
- f"<small>{esc(feels_str)}</small>" if feels_str else "",
- f"<b>{esc(min_max)}</b>" if min_max else "",
- f"{esc(wind_text)}\t{esc(humidity_text)}",
- f"{esc(visibility_text)}\t{esc(aqi_text)}",
- f"<i> {esc(prediction)}</i>" if prediction else "",
- )
- else:
- lines = [
- f"{icon} {temp_str}",
- status,
- location_text,
- ]
- if feels_str:
- lines.append(feels_str)
- if min_max:
- lines.append(min_max)
- lines.append(f"{wind_text} {humidity_text}".strip())
- lines.append(f"{visibility_text} {aqi_text}".strip())
- if prediction:
- lines.append(hourly_precip)
- tooltip_text = "\n".join([ln for ln in lines if ln])
-
- out_data = {
- "text": f"{icon} {temp_str}",
- "alt": status,
- "tooltip": tooltip_text,
- "class": code_for_class,
- }
-
- simple_weather = (
- f"{icon} {status}\n"
- + f" {temp_str} ({feels_str})\n"
- + (f"{wind_text} \n" if wind_text else "")
- + (f"{humidity_text} \n" if humidity_text else "")
- + f"{visibility_text} {aqi_text}\n"
- )
-
- return out_data, simple_weather
-
-
-def main() -> None:
- lat, lon = get_coords()
-
- # Try cache first
- cached = read_api_cache()
- if cached and isinstance(cached, dict):
- forecast = cached.get("forecast")
- aqi = cached.get("aqi")
- cached_place = cached.get("place") if isinstance(cached.get("place"), str) else None
- place_effective = MANUAL_PLACE or ENV_PLACE or cached_place
- try:
- out, simple = build_output(lat, lon, forecast, aqi, place_effective)
- print(json.dumps(out, ensure_ascii=False))
- write_simple_text_cache(simple)
- return
- except Exception as e:
- print(f"Cached data build failed, refetching: {e}", file=sys.stderr)
-
- # Fetch fresh
- try:
- forecast = fetch_open_meteo(lat, lon)
- aqi = fetch_aqi(lat, lon)
- # Use manual/env place if provided; otherwise reverse geocode
- place_effective = MANUAL_PLACE or ENV_PLACE or fetch_place(lat, lon)
- write_api_cache({"forecast": forecast, "aqi": aqi, "place": place_effective})
- out, simple = build_output(lat, lon, forecast, aqi, place_effective)
- print(json.dumps(out, ensure_ascii=False))
- write_simple_text_cache(simple)
- except Exception as e:
- print(f"Open-Meteo fetch failed: {e}", file=sys.stderr)
- # Last resort: try stale cache without TTL
- try:
- if os.path.exists(API_CACHE_PATH):
- with open(API_CACHE_PATH, "r", encoding="utf-8") as f:
- stale = json.load(f)
- out, simple = build_output(lat, lon, stale.get("forecast", {}), stale.get("aqi"), stale.get("place") if isinstance(stale.get("place"), str) else None)
- print(json.dumps(out, ensure_ascii=False))
- write_simple_text_cache(simple)
- return
- except Exception as e2:
- print(f"Failed to use stale cache: {e2}", file=sys.stderr)
- # Fallback minimal output
- fallback = {
- "text": f"{WEATHER_ICONS['default']} N/A",
- "alt": "Unavailable",
- "tooltip": "Weather unavailable",
- "class": "unavailable",
- }
- print(json.dumps(fallback, ensure_ascii=False))
-
-
-if __name__ == "__main__":
- main()
-status = html_data("div[data-testid='wxPhrase']").text()
-status = f"{status[:16]}.." if len(status) > 17 else status
-
-# status code
-status_code = html_data("#regionHeader").attr("class").split(" ")[2].split("-")[2]
-
-# status icon
-icon = (
- weather_icons[status_code]
- if status_code in weather_icons
- else weather_icons["default"]
-)
-
-# temperature feels like
-temp_feel = html_data(
- "div[data-testid='FeelsLikeSection'] > span > span[data-testid='TemperatureValue']"
-).text()
-temp_feel_text = f"Feels like {temp_feel}c"
-
-# min-max temperature
-temp_min = (
- html_data("div[data-testid='wxData'] > span[data-testid='TemperatureValue']")
- .eq(1)
- .text()
-)
-temp_max = (
- html_data("div[data-testid='wxData'] > span[data-testid='TemperatureValue']")
- .eq(0)
- .text()
-)
-temp_min_max = f" {temp_min}\t\t {temp_max}"
-
-# wind speed
-wind_speed = html_data("span[data-testid='Wind']").text().split("\n")[1]
-wind_text = f" {wind_speed}"
-
-# humidity
-humidity = html_data("span[data-testid='PercentageValue']").text()
-humidity_text = f" {humidity}"
-
-# visibility
-visibility = html_data("span[data-testid='VisibilityValue']").text()
-visibility_text = f" {visibility}"
-
-# air quality index
-air_quality_index = html_data("text[data-testid='DonutChartValue']").text()
-
-# hourly rain prediction
-prediction = html_data("section[aria-label='Hourly Forecast']")(
- "div[data-testid='SegmentPrecipPercentage'] > span"
-).text()
-prediction = prediction.replace("Chance of Rain", "")
-prediction = f"\n\n (hourly) {prediction}" if len(prediction) > 0 else prediction
-
-# tooltip text
-tooltip_text = str.format(
- "\t\t{}\t\t\n{}\n{}\n{}\n\n{}\n{}\n{}{}",
- f'<span size="xx-large">{temp}</span>',
- f"<big> {icon}</big>",
- f"<b>{status}</b>",
- f"<small>{temp_feel_text}</small>",
- f"<b>{temp_min_max}</b>",
- f"{wind_text}\t{humidity_text}",
- f"{visibility_text}\tAQI {air_quality_index}",
- f"<i> {prediction}</i>",
-)
-
-# print waybar module data
-out_data = {
- "text": f"{icon} {temp}",
- "alt": status,
- "tooltip": tooltip_text,
- "class": status_code,
-=======
-WMO_STATUS = {
- 0: "Clear sky",
- 1: "Mainly clear",
- 2: "Partly cloudy",
- 3: "Overcast",
- 45: "Fog",
- 48: "Depositing rime fog",
- 51: "Light drizzle",
- 53: "Moderate drizzle",
- 55: "Dense drizzle",
- 56: "Freezing drizzle",
- 57: "Freezing drizzle",
- 61: "Light rain",
- 63: "Moderate rain",
- 65: "Heavy rain",
- 66: "Freezing rain",
- 67: "Freezing rain",
- 71: "Slight snow",
- 73: "Moderate snow",
- 75: "Heavy snow",
- 77: "Snow grains",
- 80: "Rain showers",
- 81: "Rain showers",
- 82: "Violent rain showers",
- 85: "Snow showers",
- 86: "Heavy snow showers",
- 95: "Thunderstorm",
- 96: "Thunderstorm w/ hail",
- 99: "Thunderstorm w/ hail",
->>>>>>> 2a5a7c5 (Weather.py: switch to Open-Meteo; add caching, reverse geocoding, robust geolocation, and config options)
-}
-
-
-def wmo_to_icon(code: int, is_day: int) -> str:
- day = bool(is_day)
- if code == 0:
- return WEATHER_ICONS["sunnyDay" if day else "clearNight"]
- if code in (1, 2, 3, 45, 48):
- return WEATHER_ICONS["cloudyFoggyDay" if day else "cloudyFoggyNight"]
- if code in (51, 53, 55, 61, 63, 65, 80, 81, 82):
- return WEATHER_ICONS["rainyDay" if day else "rainyNight"]
- if code in (56, 57, 66, 67, 71, 73, 75, 77, 85, 86):
- return WEATHER_ICONS["snowyIcyDay" if day else "snowyIcyNight"]
- if code in (95, 96, 99):
- return WEATHER_ICONS["severe"]
- return WEATHER_ICONS["default"]
-
-
-def wmo_to_status(code: int) -> str:
- return WMO_STATUS.get(code, "Unknown")
-
-
-# =============== Utilities ===============
-
-def esc(s: Optional[str]) -> str:
- return html.escape(s, quote=False) if s else ""
-
-def log_debug(msg: str) -> None:
- if DEBUG:
- print(msg, file=sys.stderr)
-
-def ensure_cache_dir() -> None:
- try:
- os.makedirs(CACHE_DIR, exist_ok=True)
- except Exception as e:
- print(f"Error creating cache dir: {e}", file=sys.stderr)
-
-
-def read_api_cache() -> Optional[Dict[str, Any]]:
- try:
- if not os.path.exists(API_CACHE_PATH):
- return None
- with open(API_CACHE_PATH, "r", encoding="utf-8") as f:
- data = json.load(f)
- if (time.time() - data.get("timestamp", 0)) <= CACHE_TTL_SECONDS:
- return data
- return None
- except Exception as e:
- print(f"Error reading cache: {e}", file=sys.stderr)
- return None
-
-
-def write_api_cache(payload: Dict[str, Any]) -> None:
- try:
- ensure_cache_dir()
- payload["timestamp"] = time.time()
- with open(API_CACHE_PATH, "w", encoding="utf-8") as f:
- json.dump(payload, f)
- except Exception as e:
- print(f"Error writing API cache: {e}", file=sys.stderr)
-
-
-def write_simple_text_cache(text: str) -> None:
- try:
- ensure_cache_dir()
- with open(SIMPLE_TEXT_CACHE_PATH, "w", encoding="utf-8") as f:
- f.write(text)
- except Exception as e:
- print(f"Error writing simple cache: {e}", file=sys.stderr)
-
-
-def get_coords() -> Tuple[float, float]:
- # 1) Explicit env
- if ENV_LAT and ENV_LON:
- try:
- return float(ENV_LAT), float(ENV_LON)
- except ValueError:
- print("Invalid WEATHER_LAT/WEATHER_LON; falling back to IP geolocation", file=sys.stderr)
-
- # 2) Try cached coordinates from last successful forecast
- try:
- cached = read_api_cache()
- if cached and isinstance(cached, dict):
- fc = cached.get("forecast") or {}
- lat = fc.get("latitude")
- lon = fc.get("longitude")
- if isinstance(lat, (int, float)) and isinstance(lon, (int, float)):
- return float(lat), float(lon)
- except Exception as e:
- print(f"Reading cached coords failed: {e}", file=sys.stderr)
-
- # 3) IP-based geolocation with multiple providers (prefer ipwho.is, ipapi.co; ipinfo.io as fallback)
- # ipwho.is
- try:
- resp = SESSION.get("https://ipwho.is/", timeout=TIMEOUT)
- resp.raise_for_status()
- data = resp.json()
- if data.get("success"):
- lat = data.get("latitude")
- lon = data.get("longitude")
- if isinstance(lat, (int, float)) and isinstance(lon, (int, float)):
- return float(lat), float(lon)
- except Exception as e:
- print(f"ipwho.is failed: {e}", file=sys.stderr)
-
- # ipapi.co
- try:
- resp = SESSION.get("https://ipapi.co/json", timeout=TIMEOUT)
- resp.raise_for_status()
- data = resp.json()
- lat = data.get("latitude")
- lon = data.get("longitude")
- if isinstance(lat, (int, float)) and isinstance(lon, (int, float)):
- return float(lat), float(lon)
- except Exception as e:
- print(f"ipapi.co failed: {e}", file=sys.stderr)
-
- # ipinfo.io (fallback)
- try:
- resp = SESSION.get("https://ipinfo.io/json", timeout=TIMEOUT)
- resp.raise_for_status()
- data = resp.json()
- loc = data.get("loc")
- if loc and "," in loc:
- lat_s, lon_s = loc.split(",", 1)
- return float(lat_s), float(lon_s)
- except Exception as e:
- print(f"ipinfo.io failed: {e}", file=sys.stderr)
-
- # 4) Last resort
- print("IP geolocation failed: no providers succeeded", file=sys.stderr)
- return 0.0, 0.0
-
-
-def units_params(units: str) -> Dict[str, str]:
- if units == "imperial":
- return {
- "temperature_unit": "fahrenheit",
- "wind_speed_unit": "mph",
- "precipitation_unit": "inch",
- }
- # default metric
- return {
- "temperature_unit": "celsius",
- "wind_speed_unit": "kmh",
- "precipitation_unit": "mm",
- }
-
-
-def format_visibility(meters: Optional[float]) -> str:
- if meters is None:
- return ""
- try:
- if UNITS == "imperial":
- miles = meters / 1609.344
- return f"{miles:.1f} mi"
- else:
- km = meters / 1000.0
- return f"{km:.1f} km"
- except Exception:
- return ""
-
-
-# =============== API Fetching ===============
-
-def fetch_open_meteo(lat: float, lon: float) -> Dict[str, Any]:
- base = "https://api.open-meteo.com/v1/forecast"
- params = {
- "latitude": lat,
- "longitude": lon,
- "current": "temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_direction_10m,weather_code,visibility,precipitation,pressure_msl,is_day",
"hourly": "precipitation_probability",
"daily": "temperature_2m_max,temperature_2m_min",
"timezone": "auto",
diff --git a/config/hypr/scripts/Hyprsunset.sh b/config/hypr/scripts/Hyprsunset.sh
new file mode 100755
index 00000000..c7c4b395
--- /dev/null
+++ b/config/hypr/scripts/Hyprsunset.sh
@@ -0,0 +1,99 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Hyprsunset toggle + Waybar status helper
+# Phase 1: manual toggle only (no scheduling)
+# Icons:
+# - Off: bright sun
+# - On: sunset icon if available, otherwise a blue sun
+#
+# Customize via env vars:
+# HYPERSUNSET_TEMP default 4500 (K)
+# HYPERSUNSET_ICON_MODE sunset|blue (default: sunset)
+
+STATE_FILE="$HOME/.cache/.hyprsunset_state"
+TARGET_TEMP="${HYPERSUNSET_TEMP:-4500}"
+ICON_MODE="${HYPERSUNSET_ICON_MODE:-sunset}"
+
+ensure_state() {
+ [[ -f "$STATE_FILE" ]] || echo "off" > "$STATE_FILE"
+}
+
+# Render icons using pango markup to allow colorization
+icon_off() {
+ # universally available sun symbol
+ printf "☀"
+}
+
+icon_on() {
+ case "$ICON_MODE" in
+ sunset)
+ # sunset emoji (falls back to tofu if no emoji font)
+ printf "🌇"
+ ;;
+ blue)
+ # no color in text; rely on CSS .on to style if desired
+ printf "☀"
+ ;;
+ *)
+ printf "☀"
+ ;;
+ esac
+}
+
+cmd_toggle() {
+ ensure_state
+ state="$(cat "$STATE_FILE" || echo off)"
+
+ # Always stop any running hyprsunset first to avoid CTM manager conflicts
+ if pgrep -x hyprsunset >/dev/null 2>&1; then
+ pkill -x hyprsunset || true
+ # give it a moment to release the CTM manager
+ sleep 0.2
+ fi
+
+if [[ "$state" == "on" ]]; then
+ # Turning OFF: set identity and exit
+ if command -v hyprsunset >/dev/null 2>&1; then
+ nohup hyprsunset -i >/dev/null 2>&1 &
+ # if hyprsunset persists, stop it shortly after applying identity
+ sleep 0.3 && pkill -x hyprsunset || true
+ fi
+ echo off > "$STATE_FILE"
+ notify-send -u low "Hyprsunset: Disabled" || true
+ else
+ # Turning ON: start hyprsunset at target temp in background
+ if command -v hyprsunset >/dev/null 2>&1; then
+ nohup hyprsunset -t "$TARGET_TEMP" >/dev/null 2>&1 &
+ fi
+ echo on > "$STATE_FILE"
+ notify-send -u low "Hyprsunset: Enabled" "${TARGET_TEMP}K" || true
+ fi
+}
+
+cmd_status() {
+ ensure_state
+ # Prefer live process detection; fall back to state file
+ if pgrep -x hyprsunset >/dev/null 2>&1; then
+ onoff="on"
+ else
+ onoff="$(cat "$STATE_FILE" || echo off)"
+ fi
+
+ if [[ "$onoff" == "on" ]]; then
+ txt="<span size='18pt'>$(icon_on)</span>"
+ cls="on"
+ tip="Night light on @ ${TARGET_TEMP}K"
+ else
+ txt="<span size='16pt'>$(icon_off)</span>"
+ cls="off"
+ tip="Night light off"
+ fi
+ printf '{"text":"%s","class":"%s","tooltip":"%s"}\n' "$txt" "$cls" "$tip"
+}
+
+case "${1:-}" in
+ toggle) cmd_toggle ;;
+ status) cmd_status ;;
+ *) echo "usage: $0 [toggle|status]" >&2; exit 2 ;;
+ esac
diff --git a/config/hypr/scripts/MediaCtrl.sh b/config/hypr/scripts/MediaCtrl.sh
index 2cbeccf3..000c3ade 100755
--- a/config/hypr/scripts/MediaCtrl.sh
+++ b/config/hypr/scripts/MediaCtrl.sh
@@ -6,56 +6,57 @@ music_icon="$HOME/.config/swaync/icons/music.png"
# Play the next track
play_next() {
- playerctl next
- show_music_notification
+ playerctl next
+ show_music_notification
}
# Play the previous track
play_previous() {
- playerctl previous
- show_music_notification
+ playerctl previous
+ show_music_notification
}
# Toggle play/pause
toggle_play_pause() {
- playerctl play-pause
- show_music_notification
+ playerctl play-pause
+ sleep 0.1
+ show_music_notification
}
# Stop playback
stop_playback() {
- playerctl stop
- notify-send -e -u low -i $music_icon " Playback:" " Stopped"
+ playerctl stop
+ notify-send -e -u low -i $music_icon " Playback:" " Stopped"
}
# Display notification with song information
show_music_notification() {
- status=$(playerctl status)
- if [[ "$status" == "Playing" ]]; then
- song_title=$(playerctl metadata title)
- song_artist=$(playerctl metadata artist)
- notify-send -e -u low -i $music_icon "Now Playing:" "$song_title by $song_artist"
- elif [[ "$status" == "Paused" ]]; then
- notify-send -e -u low -i $music_icon " Playback:" " Paused"
- fi
+ status=$(playerctl status)
+ if [[ "$status" == "Playing" ]]; then
+ song_title=$(playerctl metadata title)
+ song_artist=$(playerctl metadata artist)
+ notify-send -e -u low -i $music_icon "Now Playing:" "$song_title by $song_artist"
+ elif [[ "$status" == "Paused" ]]; then
+ notify-send -e -u low -i $music_icon " Playback:" " Paused"
+ fi
}
# Get media control action from command line argument
case "$1" in
- "--nxt")
- play_next
- ;;
- "--prv")
- play_previous
- ;;
- "--pause")
- toggle_play_pause
- ;;
- "--stop")
- stop_playback
- ;;
- *)
- echo "Usage: $0 [--nxt|--prv|--pause|--stop]"
- exit 1
- ;;
+"--nxt")
+ play_next
+ ;;
+"--prv")
+ play_previous
+ ;;
+"--pause")
+ toggle_play_pause
+ ;;
+"--stop")
+ stop_playback
+ ;;
+*)
+ echo "Usage: $0 [--nxt|--prv|--pause|--stop]"
+ exit 1
+ ;;
esac
diff --git a/config/hypr/scripts/sddm_wallpaper.sh b/config/hypr/scripts/sddm_wallpaper.sh
index a781156e..9487188c 100644
--- a/config/hypr/scripts/sddm_wallpaper.sh
+++ b/config/hypr/scripts/sddm_wallpaper.sh
@@ -10,7 +10,12 @@ wallDIR="$HOME/Pictures/wallpapers"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current"
wallpaper_modified="$HOME/.config/hypr/wallpaper_effects/.wallpaper_modified"
-sddm_simple="/usr/share/sddm/themes/simple_sddm_2"
+# Resolve SDDM themes directory (standard paths and NixOS path)
+sddm_themes_dir="/usr/share/sddm/themes"
+if [ ! -d "$sddm_themes_dir" ] && [ -d "/run/current-system/sw/share/sddm/themes" ]; then
+ sddm_themes_dir="/run/current-system/sw/share/sddm/themes"
+fi
+sddm_simple="$sddm_themes_dir/simple_sddm_2"
# rofi-wallust-sddm colors path
rofi_wallust="$HOME/.config/rofi/wallust/colors-rofi.rasi"
@@ -46,6 +51,12 @@ else
wallpaper_path="$wallpaper_modified"
fi
+# Abort on NixOS where this repo doesn't manage SDDM and themes are typically read-only
+if hostnamectl 2>/dev/null | grep -q 'Operating System: NixOS'; then
+ notify-send -i "$iDIR/error.png" "SDDM" "NixOS detected: skipping SDDM background change."
+ exit 0
+fi
+
# Launch terminal and apply changes
$terminal -e bash -c "
echo 'Enter your password to update SDDM wallpapers and colors';
@@ -70,7 +81,15 @@ sudo sed -i \"s/UserIconColor=\\\"#.*\\\"/UserIconColor=\\\"$color7\\\"/\" \"$sd
sudo sed -i \"s/PasswordIconColor=\\\"#.*\\\"/PasswordIconColor=\\\"$color7\\\"/\" \"$sddm_theme_conf\"
# Copy wallpaper to SDDM theme
-sudo cp \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default\"
+# Primary: set Backgrounds/default (no extension) for simple_sddm_2
+sudo cp -f \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default\" || true
+# Fallbacks: if theme ships default.jpg or default.png, update those too
+if [ -e \"$sddm_simple/Backgrounds/default.jpg\" ]; then
+ sudo cp -f \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default.jpg\"
+fi
+if [ -e \"$sddm_simple/Backgrounds/default.png\" ]; then
+ sudo cp -f \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default.png\"
+fi
notify-send -i \"$iDIR/ja.png\" \"SDDM\" \"Background SET\"
" \ No newline at end of file
diff --git a/config/hypr/v2.3.16 b/config/hypr/v2.3.16
deleted file mode 100644
index 31b3414d..00000000
--- a/config/hypr/v2.3.16
+++ /dev/null
@@ -1,5 +0,0 @@
-### https://github.com/JaKooLit ###
-## https://github.com/JaKooLit/Hyprland-Dots
-## This is to have a reference of which version would be
-
-## note that this will always be higher than the released versions \ No newline at end of file
diff --git a/config/quickshell/modules/common/ConfigOptions.qml b/config/quickshell/modules/common/ConfigOptions.qml
index 25f0de05..3a9fa194 100644
--- a/config/quickshell/modules/common/ConfigOptions.qml
+++ b/config/quickshell/modules/common/ConfigOptions.qml
@@ -17,6 +17,7 @@ Singleton {
property real windowPadding: 6
property real position: 1 // 0: top | 1: middle | 2: bottom
property real workspaceNumberSize: 120 // Set 0, dynamic calculation based on monitor size
+ property bool showAllMonitors: true // Show windows from all monitors
}
property QtObject resources: QtObject {
diff --git a/config/quickshell/modules/overview/Overview.qml b/config/quickshell/modules/overview/Overview.qml
index ef5a49c3..08a3b0d3 100644
--- a/config/quickshell/modules/overview/Overview.qml
+++ b/config/quickshell/modules/overview/Overview.qml
@@ -17,7 +17,7 @@ Scope {
Variants {
id: overviewVariants
- model: Quickshell.screens
+ model: Quickshell.screens.filter(s => Hyprland.monitorFor(s).id === Hyprland.focusedMonitor?.id)
PanelWindow {
id: root
required property var modelData
diff --git a/config/quickshell/modules/overview/OverviewWidget.qml b/config/quickshell/modules/overview/OverviewWidget.qml
index 93e90967..05a15e10 100644
--- a/config/quickshell/modules/overview/OverviewWidget.qml
+++ b/config/quickshell/modules/overview/OverviewWidget.qml
@@ -46,6 +46,33 @@ Item {
property int draggingFromWorkspace: -1
property int draggingTargetWorkspace: -1
+ // Debug logging function
+ function debugMultiMonitorInfo() {
+ console.log("=== Multi-Monitor Debug Info ===")
+ console.log("Current monitor ID:", root.monitor.id)
+ console.log("Current monitor name:", root.monitor.name)
+ console.log("Current monitor scale:", root.monitor.scale)
+ console.log("Current monitor position:", root.monitor.x, root.monitor.y)
+ console.log("Total monitors:", HyprlandData.monitors.length)
+
+ HyprlandData.monitors.forEach((mon, idx) => {
+ console.log(`Monitor ${idx}: ID=${mon.id}, Name=${mon.name}, Scale=${mon.scale}, Pos=(${mon.x},${mon.y}), Size=${mon.width}x${mon.height}, Reserved=[${mon.reserved.join(",")}]`)
+ })
+
+ console.log("Total windows:", windowAddresses.length)
+ windowAddresses.forEach((address, idx) => {
+ const win = windowByAddress[address]
+ if (win) {
+ console.log(`Window ${idx}: ${win.class} on monitor ${win.monitor}, workspace ${win.workspace?.id}, pos=(${win.at[0]},${win.at[1]})`)
+ }
+ })
+ console.log("=== End Debug Info ===")
+ }
+
+ Component.onCompleted: {
+ debugMultiMonitorInfo()
+ }
+
implicitWidth: overviewBackground.implicitWidth + Appearance.sizes.elevationMargin * 2
implicitHeight: overviewBackground.implicitHeight + Appearance.sizes.elevationMargin * 2
@@ -233,14 +260,21 @@ Item {
model: ScriptModel {
values: windowAddresses.filter((address) => {
var win = windowByAddress[address]
- return (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown)
+ if (!win) return false
+
+ // Filter by workspace group AND monitor if configured
+ const inWorkspaceGroup = (root.workspaceGroup * root.workspacesShown < win?.workspace?.id &&
+ win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown)
+ const inMonitor = ConfigOptions.overview.showAllMonitors || win.monitor === root.monitor.id
+
+ return inWorkspaceGroup && inMonitor
})
}
delegate: OverviewWindow {
id: window
windowData: windowByAddress[modelData]
- monitorData: HyprlandData.monitors.find(m => m.id === windowData?.monitor) // use monitorData of the monitor the window is on
- scale: root.scale * (monitorData?.scale / root.monitor?.scale) // adjust window scale to the monitor where the overview is displayed
+ monitorData: root.monitorData
+ scale: root.scale
availableWorkspaceWidth: root.workspaceImplicitWidth
availableWorkspaceHeight: root.workspaceImplicitHeight
diff --git a/config/quickshell/modules/overview/OverviewWindow.qml b/config/quickshell/modules/overview/OverviewWindow.qml
index 93ea06f9..b28a5bf6 100644
--- a/config/quickshell/modules/overview/OverviewWindow.qml
+++ b/config/quickshell/modules/overview/OverviewWindow.qml
@@ -17,14 +17,31 @@ Rectangle { // Window
property var scale
property var availableWorkspaceWidth
property var availableWorkspaceHeight
- property bool restrictToWorkspace: true
- property real initX: Math.max((windowData?.at[0] - monitorData?.reserved[0] - monitorData?.x) * root.scale, 0) + xOffset
- property real initY: Math.max((windowData?.at[1] - monitorData?.reserved[1] - monitorData?.y) * root.scale, 0) + yOffset
+ property bool restrictToWorkspace: true``
+ property var sourceMonitor: HyprlandData.monitors.find(m => m.id === windowData?.monitor) || HyprlandData.monitors[0] || { scale: 1.0, x: 0, y: 0, reserved: [0,0,0,0] }
+ property real monitorScaleFactor: sourceMonitor?.scale || 1.0
+ property real targetScaleFactor: monitorData?.scale || monitorScaleFactor || 1.0
+ property var focusedMonitor: Hyprland.focusedMonitor
+ property real focusedMonitorScale: focusedMonitor?.scale || 1.0
+ property real effectiveScale: root.scale * (
+ ConfigOptions.overview.showAllMonitors
+ ? (focusedMonitorScale / monitorScaleFactor) // Scale relative to focused monitor when showing all
+ : (targetScaleFactor / monitorScaleFactor) // Scale relative to target monitor normally
+ )
+
+ // Calculate position relative to source monitor
+ property real relativeX: (windowData?.at[0] - sourceMonitor?.x - sourceMonitor?.reserved[0]) || 0
+ property real relativeY: (windowData?.at[1] - sourceMonitor?.y - sourceMonitor?.reserved[1]) || 0
+
+ // Scale position based on monitor differences
+ property real initX: Math.max(relativeX * effectiveScale, 0) + xOffset
+ property real initY: Math.max(relativeY * effectiveScale, 0) + yOffset
property real xOffset: 0
property real yOffset: 0
- property var targetWindowWidth: windowData?.size[0] * scale
- property var targetWindowHeight: windowData?.size[1] * scale
+ // Scale window size based on monitor differences
+ property var targetWindowWidth: (windowData?.size[0] || 0) * effectiveScale
+ property var targetWindowHeight: (windowData?.size[1] || 0) * effectiveScale
property bool hovered: false
property bool pressed: false
diff --git a/config/waybar/ModulesCustom b/config/waybar/ModulesCustom
index dddc5ccc..146ec275 100644
--- a/config/waybar/ModulesCustom
+++ b/config/waybar/ModulesCustom
@@ -104,6 +104,19 @@
"tooltip-format": "Left Click: Switch Dark-Light Themes\nMiddle Click: Wallpaper Menu\nRight Click: Waybar Styles Menu",
},
+// Night light (Hyprsunset)
+"custom/nightlight": {
+ "return-type": "json",
+ "exec": "$HOME/.config/hypr/scripts/Hyprsunset.sh status",
+ "interval": 3,
+ "format": "{text}",
+ "min-length": 2,
+ "on-click": "$HOME/.config/hypr/scripts/Hyprsunset.sh toggle",
+ "tooltip": true,
+ "tooltip-format": "Night light toggle",
+ "escape": false
+},
+
"custom/lock": {
"format": "󰌾",
"on-click": "$HOME/.config/hypr/scripts/LockScreen.sh",
diff --git a/config/waybar/ModulesGroups b/config/waybar/ModulesGroups
index 30e47f16..8d4453a2 100644
--- a/config/waybar/ModulesGroups
+++ b/config/waybar/ModulesGroups
@@ -89,6 +89,7 @@
},
"modules": [
"custom/power",
+ "custom/nightlight",
"custom/lock",
"keyboard-state",
"custom/keyboard",
@@ -131,6 +132,7 @@
},
"modules": [
"custom/power",
+ "custom/nightlight",
"custom/lock",
"custom/logout",
"custom/reboot"
diff --git a/config/waybar/configs/[BOT & Left] SouthWest b/config/waybar/configs/[BOT & Left] SouthWest
index a039f040..594b46d3 100644
--- a/config/waybar/configs/[BOT & Left] SouthWest
+++ b/config/waybar/configs/[BOT & Left] SouthWest
@@ -46,6 +46,7 @@
"power-profiles-daemon",
"pulseaudio#microphone",
"keyboard-state",
+ "custom/nightlight",
"custom/power",
],
},
diff --git a/config/waybar/configs/[BOT & Right] SouthEast b/config/waybar/configs/[BOT & Right] SouthEast
index 9a58e952..03cdb06c 100644
--- a/config/waybar/configs/[BOT & Right] SouthEast
+++ b/config/waybar/configs/[BOT & Right] SouthEast
@@ -46,6 +46,7 @@
"power-profiles-daemon",
"pulseaudio#microphone",
"keyboard-state",
+ "custom/nightlight",
"custom/power",
],
},
diff --git a/config/waybar/configs/[LEFT] WestWing b/config/waybar/configs/[LEFT] WestWing
index e3f25d1a..28e5dbec 100644
--- a/config/waybar/configs/[LEFT] WestWing
+++ b/config/waybar/configs/[LEFT] WestWing
@@ -39,6 +39,7 @@
"backlight#vertical",
"pulseaudio#microphone_vertical",
"pulseaudio#vertical",
+ "custom/nightlight",
"custom/power_vertical",
"custom/menu",
],
diff --git a/config/waybar/configs/[LEFT] WestWing v2 b/config/waybar/configs/[LEFT] WestWing v2
index f1ed69c3..906f83d6 100644
--- a/config/waybar/configs/[LEFT] WestWing v2
+++ b/config/waybar/configs/[LEFT] WestWing v2
@@ -40,6 +40,7 @@
"backlight#vertical",
"pulseaudio/slider",
"pulseaudio#microphone_vertical",
+ "custom/nightlight",
"group/power#vert",
],
diff --git a/config/waybar/configs/[RIGHT] EastWing b/config/waybar/configs/[RIGHT] EastWing
index b64fe5f8..a5ce6756 100644
--- a/config/waybar/configs/[RIGHT] EastWing
+++ b/config/waybar/configs/[RIGHT] EastWing
@@ -39,6 +39,7 @@
"backlight#vertical",
"pulseaudio#microphone_vertical",
"pulseaudio#vertical",
+ "custom/nightlight",
"custom/power_vertical",
"custom/menu",
],
diff --git a/config/waybar/configs/[RIGHT] EastWing v2 b/config/waybar/configs/[RIGHT] EastWing v2
index f9991bd6..28dd1e43 100644
--- a/config/waybar/configs/[RIGHT] EastWing v2
+++ b/config/waybar/configs/[RIGHT] EastWing v2
@@ -40,6 +40,7 @@
"backlight#vertical",
"pulseaudio/slider",
"pulseaudio#microphone_vertical",
+ "custom/nightlight",
"group/power#vert",
],
diff --git a/config/waybar/configs/[TOP & BOT] SummitSplit b/config/waybar/configs/[TOP & BOT] SummitSplit
index 03c8e81b..516e9834 100644
--- a/config/waybar/configs/[TOP & BOT] SummitSplit
+++ b/config/waybar/configs/[TOP & BOT] SummitSplit
@@ -44,6 +44,7 @@
"network",
"custom/updater",
"custom/cycle_wall",
+ "custom/nightlight",
"custom/lock",
],
},
@@ -88,6 +89,7 @@
"pulseaudio",
//"wireplumber",
"pulseaudio#microphone",
+ "custom/nightlight",
"custom/power",
],
}],
diff --git a/config/waybar/configs/[TOP & BOT] SummitSplit v2 b/config/waybar/configs/[TOP & BOT] SummitSplit v2
index 1425f657..4d576aef 100644
--- a/config/waybar/configs/[TOP & BOT] SummitSplit v2
+++ b/config/waybar/configs/[TOP & BOT] SummitSplit v2
@@ -28,13 +28,14 @@
"network",
],
"modules-center": ["hyprland/window"],
- "modules-right": [
+"modules-right": [
"mpris",
"battery",
"backlight",
"pulseaudio",
"group/mobo_drawer",
"idle_inhibitor",
+ "custom/nightlight",
"group/power"
],
diff --git a/config/waybar/configs/[TOP] 0-Ja-0 b/config/waybar/configs/[TOP] 0-Ja-0
index c4cb0a65..6e7fc9aa 100644
--- a/config/waybar/configs/[TOP] 0-Ja-0
+++ b/config/waybar/configs/[TOP] 0-Ja-0
@@ -48,6 +48,7 @@
"custom/separator#dot-line",
"mpris",
"custom/separator#blank",
+ "custom/nightlight",
"group/status",
],
} \ No newline at end of file
diff --git a/config/waybar/configs/[TOP] Arrow b/config/waybar/configs/[TOP] Arrow
index 8001d8fb..7fc55f60 100644
--- a/config/waybar/configs/[TOP] Arrow
+++ b/config/waybar/configs/[TOP] Arrow
@@ -36,7 +36,8 @@
"battery",
"custom/arrow2",
"tray",
- "custom/arrow1",
+"custom/arrow1",
+ "custom/nightlight",
"clock#2"
],
}
diff --git a/config/waybar/configs/[TOP] Camellia b/config/waybar/configs/[TOP] Camellia
index c93e9079..efaf6e20 100644
--- a/config/waybar/configs/[TOP] Camellia
+++ b/config/waybar/configs/[TOP] Camellia
@@ -44,7 +44,8 @@
"power-profiles-daemon",
"battery",
"clock#3",
- "network"],
+ "network",
+ "custom/nightlight"],
// Additional modules //
"pulseaudio/slider": {
diff --git a/config/waybar/configs/[TOP] Chrysanthemum b/config/waybar/configs/[TOP] Chrysanthemum
index ebaa0ca4..d12f73e3 100644
--- a/config/waybar/configs/[TOP] Chrysanthemum
+++ b/config/waybar/configs/[TOP] Chrysanthemum
@@ -36,6 +36,7 @@
"modules-right": [
"pulseaudio#1",
"backlight#2",
- "battery"],
+ "battery",
+ "custom/nightlight"],
} \ No newline at end of file
diff --git a/config/waybar/configs/[TOP] Default Laptop b/config/waybar/configs/[TOP] Default Laptop
index b9722b89..0b264c6b 100644
--- a/config/waybar/configs/[TOP] Default Laptop
+++ b/config/waybar/configs/[TOP] Default Laptop
@@ -54,6 +54,7 @@
"custom/separator#line",
"group/audio",
"custom/separator#dot-line",
+ "custom/nightlight",
"group/status",
],
} \ No newline at end of file
diff --git a/config/waybar/configs/[TOP] Everforest b/config/waybar/configs/[TOP] Everforest
index a66763ed..7b007f78 100644
--- a/config/waybar/configs/[TOP] Everforest
+++ b/config/waybar/configs/[TOP] Everforest
@@ -45,6 +45,7 @@
"battery#forest",
"custom/separator#blank_2",
"group/audio",
+ "custom/nightlight",
],
// Additional / Edited Waybar Modules //
diff --git a/config/waybar/configs/[TOP] Gardenia b/config/waybar/configs/[TOP] Gardenia
index 77e86bae..073ff46e 100644
--- a/config/waybar/configs/[TOP] Gardenia
+++ b/config/waybar/configs/[TOP] Gardenia
@@ -37,7 +37,8 @@
"modules-right": [
"pulseaudio#1",
"backlight#2",
- "battery"
+ "battery",
+ "custom/nightlight"
],
} \ No newline at end of file
diff --git a/config/waybar/configs/[TOP] Minimal - Long b/config/waybar/configs/[TOP] Minimal - Long
index b57cf3a3..a5be4bd7 100644
--- a/config/waybar/configs/[TOP] Minimal - Long
+++ b/config/waybar/configs/[TOP] Minimal - Long
@@ -42,6 +42,7 @@
"custom/separator#blank_2",
"group/audio",
"custom/separator#blank_2",
+ "custom/nightlight",
"custom/power",
],
diff --git a/config/waybar/configs/[TOP] Minimal - Short b/config/waybar/configs/[TOP] Minimal - Short
index 57abd3d3..7b9a1929 100644
--- a/config/waybar/configs/[TOP] Minimal - Short
+++ b/config/waybar/configs/[TOP] Minimal - Short
@@ -34,5 +34,6 @@
"backlight",
"pulseaudio",
"battery",
+ "custom/nightlight",
"custom/power"],
}
diff --git a/config/waybar/configs/[TOP] Peony b/config/waybar/configs/[TOP] Peony
index 2fd1dfe3..a1ef02e8 100644
--- a/config/waybar/configs/[TOP] Peony
+++ b/config/waybar/configs/[TOP] Peony
@@ -44,6 +44,7 @@
"temperature",
"custom/separator#blank",
"group/mobo_drawer",
- "network"],
+ "network",
+ "custom/nightlight"],
} \ No newline at end of file
diff --git a/config/waybar/configs/[TOP] Sleek b/config/waybar/configs/[TOP] Sleek
index fe0f41ba..f591f472 100644
--- a/config/waybar/configs/[TOP] Sleek
+++ b/config/waybar/configs/[TOP] Sleek
@@ -39,6 +39,7 @@
"pulseaudio",
"custom/separator#blank",
"group/mobo_drawer",
+ "custom/nightlight",
"custom/power",
],
}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage