mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-15 21:15:24 +02:00
Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34babe8d47 | ||
|
|
b67c15b992 | ||
|
|
dbc0532f64 | ||
|
|
18d3659d36 | ||
|
|
916c3b67d5 | ||
|
|
0151b66144 | ||
|
|
200c15b257 | ||
|
|
063b5a8032 | ||
|
|
e9b7031bec | ||
|
|
7dce8295c1 | ||
|
|
80d44a3475 | ||
|
|
49fba4af82 | ||
|
|
4b601bb196 | ||
|
|
906b338fcc | ||
|
|
ba501ff213 | ||
|
|
bc11fc7653 | ||
|
|
7f17d67e78 | ||
|
|
6f575448cf | ||
|
|
7b751ab726 | ||
|
|
b625ff98eb | ||
|
|
b9d14fa4de | ||
|
|
ad3b07097f | ||
|
|
e942f3264d | ||
|
|
0bb5708769 | ||
|
|
0c46b209b9 | ||
|
|
2905b45ef7 |
No files matched your search
@@ -34,7 +34,7 @@ jobs:
|
|||||||
.github/tools/bundle.sh dist/steamify.sh
|
.github/tools/bundle.sh dist/steamify.sh
|
||||||
# The app: sources, not the single-file build (its backend mode runs
|
# The app: sources, not the single-file build (its backend mode runs
|
||||||
# steamify.sh from its own folder).
|
# steamify.sh from its own folder).
|
||||||
tar -czf dist/steamify-app.tar.gz steamify.sh lib patches services ui assets/steam-gaming-settings.svg LICENSE.md
|
tar -czf dist/steamify-app.tar.gz steamify.sh lib patches services ui assets/steam-gaming-settings.svg assets/steam-gaming-settings.png LICENSE.md
|
||||||
cp ui/steamify-app.sh dist/steamify-app.sh
|
cp ui/steamify-app.sh dist/steamify-app.sh
|
||||||
|
|
||||||
- name: Check
|
- name: Check
|
||||||
@@ -119,7 +119,7 @@ jobs:
|
|||||||
|
|
||||||
## Changes in v$VERSION
|
## Changes in v$VERSION
|
||||||
$changes"
|
$changes"
|
||||||
gh release create "v$VERSION" dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg \
|
gh release create "v$VERSION" dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg assets/steam-gaming-settings.png \
|
||||||
--target "$GITHUB_SHA" --title "Steamify CachyOS v$VERSION" --notes "$notes" --latest
|
--target "$GITHUB_SHA" --title "Steamify CachyOS v$VERSION" --notes "$notes" --latest
|
||||||
|
|
||||||
# "latest" follows the newest version tag, for the older install URL
|
# "latest" follows the newest version tag, for the older install URL
|
||||||
@@ -132,7 +132,7 @@ jobs:
|
|||||||
else
|
else
|
||||||
gh release create latest --title "Steamify CachyOS - latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
gh release create latest --title "Steamify CachyOS - latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
||||||
fi
|
fi
|
||||||
gh release upload latest dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg --clobber
|
gh release upload latest dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg assets/steam-gaming-settings.png --clobber
|
||||||
|
|
||||||
# The mirror (Gitea) publishes its own release per version too, the same way: never overwrites one,
|
# The mirror (Gitea) publishes its own release per version too, the same way: never overwrites one,
|
||||||
# notes from the changelog. gh can't talk to Gitea: its API for the check, a Gitea release action to
|
# notes from the changelog. gh can't talk to Gitea: its API for the check, a Gitea release action to
|
||||||
@@ -191,6 +191,7 @@ jobs:
|
|||||||
dist/steamify-app.sh
|
dist/steamify-app.sh
|
||||||
dist/steamify-app.tar.gz
|
dist/steamify-app.tar.gz
|
||||||
assets/steam-gaming-settings.svg
|
assets/steam-gaming-settings.svg
|
||||||
|
assets/steam-gaming-settings.png
|
||||||
|
|
||||||
# A new version starts the Steamify ISO's release of the ISO repo: its iso-1-github-tag.yml (always run from
|
# A new version starts the Steamify ISO's release of the ISO repo: its iso-1-github-tag.yml (always run from
|
||||||
# master) names the ISO after the newest Steamify release, tags it, and the Gitea mirror builds and attaches the ISO.
|
# master) names the ISO after the newest Steamify release, tags it, and the Gitea mirror builds and attaches the ISO.
|
||||||
|
|||||||
@@ -5,6 +5,24 @@ All notable changes, per version and per commit. Versions follow
|
|||||||
`steamify.sh`. Versions before 0.7.0 were numbered afterwards,
|
`steamify.sh`. Versions before 0.7.0 were numbered afterwards,
|
||||||
one per merged pull request.
|
one per merged pull request.
|
||||||
|
|
||||||
|
## 2.13.0 - 2026-10-15
|
||||||
|
|
||||||
|
- **feat: GNOME support (the "SteamOS theme for GNOME" option, GDM session switching, the GNOME launcher/notifier/tray behaviour): the Vapor colors, the Steam Deck wallpaper, Ubuntu Dock, Tiling Assistant, Desktop Icons NG, AppIndicator and Steamify's own Vapor shell extension, with Switch to Desktop remembering KDE or GNOME. Prototype work since 2.12.0: `5dfc916`, `fc28ea4`, `ae12c1b`, `2b84e6a`, `c5b59d9`, `62a30e6`, `039f269`, `12eb562`, `c7f5f51`, `7904833`, `ce1aa1b`, `ab3b581`, `eaa3f28`, `4221ae6`, `8432f63`, `09ef0b1`, `68342e7`, `0e0bf57`, `7a84b0d`, `dbaeaa1`**
|
||||||
|
- `2ca288d` **fix: the NVIDIA gaming mode setup no longer fails with "the patched gamescope doesn't start" on a gamescope that works: the smoke test judged gamescope's exit status through a pipe into `grep -q` under `pipefail`, so gamescope's crash on the closed pipe (or a hung shutdown) counted as a failed test, intermittently, for the CPU-specific and the generic build alike (seen on an RTX 5080). The test now reads gamescope's output from a file and kills a hung shutdown (`timeout -k`)**
|
||||||
|
- `645b331` **feat: the GNOME theme installs GNOME Settings with the "GNOME Desktop" panel (dock, desktop icons, tiling) as a prebuilt package, downloaded from the `settings` release of steamify-gnome-theme (built by GitHub Actions on current Arch, rebuilt weekly) and checked against its `.sha256`; a failure keeps the stock Settings. Turning the theme off puts the stock `gnome-control-center` back. Installs with the GNOME theme on re-apply it (feature version 2.13.0)**
|
||||||
|
- **fix: the app's logo (an SVG) shows on a fresh install: `pyside6` doesn't depend on `qt6-svg`, Qt's SVG plugin, so without it the header logo was empty and the window had no icon of its own; it is installed with PySide6 (the app's installer, the launcher, the update notifier)**
|
||||||
|
- **fix: the app's icon shows in GNOME's dock on a fresh install: GNOME couldn't draw the SVG (a blank icon: "Could not load a pixbuf from icon theme"), by path or by name. The app's installer and the launcher put a 256x256 PNG (`assets/steam-gaming-settings.png`, a release file next to the SVG) in the user's icon theme and the launchers refer to it by name; the SVG stays as the fallback for releases without the PNG**
|
||||||
|
|
||||||
|
- **feat: after the GNOME theme is applied in a GNOME session, the app's done screen has "Restart GNOME" (GNOME Shell on Wayland can't restart in place, and the dock, extensions and Settings panel only show after a new login): with GDM autologin (the SteamOS conversion) Steamify's relogin helper logs the user straight back into the session they were in (without changing the session gaming mode's boot goes back to), else it is a plain logout (`gnome-session-quit`)**
|
||||||
|
- **fix: the app on a desktop (a window, however large, also fullscreen) keeps the desktop's own scale instead of blowing its 1280x720 layout up to the screen's height (twice as big on a 1440p or ultrawide monitor): the layout fills the window at the scale of GNOME or KDE, and only a window smaller than 1280x720 shrinks it. The TV mode (`--fullscreen`, gamescope) still scales to the screen**
|
||||||
|
- **fix: in the app a click on a row only selects it (a second click on the selected row used to flip it, so a click on a switch needed two); a click on the switch itself, or on the BIOS update button, acts at once and selects the row too**
|
||||||
|
- **feat: a run that only needs a new GNOME login (the theme, no reboot) ends with a countdown on the done screen ("Restarting GNOME in 10 s", with Restart GNOME now and Cancel) and then logs in again by itself, the counterpart of KDE restarting plasmashell (GNOME Shell on Wayland is the compositor too and can't restart in place). A run that needs a reboot keeps "Restart now" (it loads GNOME fresh): before, the Restart GNOME button was hidden then, and nothing started by itself**
|
||||||
|
- **fix: Restart GNOME logs in to GNOME: after the SteamOS conversion the account's session is gaming mode, and the relogin went there (a restart that took a minute: Steam starting in gaming mode). `steamify-gdm-relogin` takes the session to log in to (the one the app runs in) for this login only and puts the account's session, the one the next boot goes to, back once the new session is up**
|
||||||
|
- **fix: turning the GNOME theme off also removes the dock's and tiling's settings schemas that were copied to `~/.local/share/glib-2.0/schemas` for GNOME Settings' panel (they stayed behind, for extensions that were gone). Desktop Icons NG and AppIndicator stay: they belong to the SteamOS conversion (the desktop shortcut and Steam's tray icon)**
|
||||||
|
- **fix: turning everything off gives GNOME back what Steamify added for the desktop and tray icons: Desktop Icons NG and AppIndicator (and Extension Manager), which the SteamOS conversion and now the GNOME theme both need. When the last of the two is turned off, the two extensions leave the user's list of enabled extensions and the packages Steamify installed (noted in `gnomeextras.list` before installing, so packages the user had stay) are removed; while the other one is still on they stay, and are enabled again (the theme's undo puts back the list it found). Before, nothing removed them. The theme installs them itself too**
|
||||||
|
- **feat: the GNOME theme puts the dock at the bottom of the screen (Ubuntu's own default is the left); it can still be moved in GNOME Settings > GNOME Desktop (the Dock panel)**
|
||||||
|
- **feat: the GNOME theme puts the desktop icons at the top right (Desktop Icons NG's start corner, like Ubuntu and macOS) and clears the saved positions of Steamify's own launchers (Return to Gaming Mode, Steamify, Steam) so they are placed from there, in name order; the user's own files keep theirs. Turning the theme off puts the start corner back**
|
||||||
|
|
||||||
## 2.12.0 - 2026-10-13
|
## 2.12.0 - 2026-10-13
|
||||||
|
|
||||||
- **feat: setting up the SteamOS conversion on NVIDIA first checks that nothing blocks it (a pacman lock, less than 1.5 GB free), and a failed setup is remembered: a desktop notification now and a reminder in the menu until a setup works**
|
- **feat: setting up the SteamOS conversion on NVIDIA first checks that nothing blocks it (a pacman lock, less than 1.5 GB free), and a failed setup is remembered: a desktop notification now and a reminder in the menu until a setup works**
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
+4
-1
@@ -195,7 +195,10 @@ backend_apply() {
|
|||||||
feature_record_unticked
|
feature_record_unticked
|
||||||
os_version_refresh
|
os_version_refresh
|
||||||
[[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " =~ \ (gaming|single|boot|kpin)\ ]] && RESTART_FOR_LOGIN=true
|
[[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " =~ \ (gaming|single|boot|kpin)\ ]] && RESTART_FOR_LOGIN=true
|
||||||
backend_event finished "\"failed\":$(json_list "${failed[@]}"),\"restart\":$(restart_needed && echo true || echo false)"
|
# (Only when the theme itself worked: a failed one has nothing to log in again for.)
|
||||||
|
local relogin=false
|
||||||
|
[[ " ${failed[*]:-} " != *" gnometheme "* ]] && gnometheme_relogin_needed "${TO_DISABLE[@]}" "${TO_ENABLE[@]}" && relogin=true
|
||||||
|
backend_event finished "\"failed\":$(json_list "${failed[@]}"),\"restart\":$(restart_needed && echo true || echo false),\"relogin\":$relogin"
|
||||||
}
|
}
|
||||||
|
|
||||||
backend_main() {
|
backend_main() {
|
||||||
|
|||||||
@@ -141,3 +141,48 @@ gnome_extensions_enable() {
|
|||||||
gsettings set org.gnome.shell enabled-extensions "$enabled"
|
gsettings set org.gnome.shell enabled-extensions "$enabled"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The packages behind them. Needed by the SteamOS conversion (the desktop shortcut's icon, Steam's tray icon) and by the
|
||||||
|
# GNOME theme (its desktop and tray icons); a PC that has neither any more gets back what Steamify added.
|
||||||
|
GNOME_EXTRA_PKGS=(gnome-shell-extension-desktop-icons-ng gnome-shell-extension-appindicator extension-manager)
|
||||||
|
|
||||||
|
gnome_extras_note_missing() {
|
||||||
|
# Before they are installed: which of them Steamify brings itself (the others were the user's: they stay), one name per
|
||||||
|
# line in a file of its own, not a state value: kwriteconfig6 (kconfig) is one of the packages installed in that step.
|
||||||
|
# Already noted ones stay noted (they are installed by then, so they aren't "missing" again).
|
||||||
|
local p list="$STATE_DIR/gnomeextras.list"
|
||||||
|
mkdir -p "$STATE_DIR"
|
||||||
|
for p in "${GNOME_EXTRA_PKGS[@]}"; do
|
||||||
|
pacman -Q "$p" >/dev/null 2>&1 || grep -qxF "$p" "$list" 2>/dev/null || echo "$p" >> "$list"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
gnome_extensions_disable() {
|
||||||
|
# The two out of the user's list of enabled extensions again.
|
||||||
|
user_session && command -v gsettings >/dev/null || return 0
|
||||||
|
local uuid enabled
|
||||||
|
for uuid in "${GNOME_EXTENSIONS[@]}"; do
|
||||||
|
enabled="$(gsettings get org.gnome.shell enabled-extensions 2>/dev/null)" || return 0
|
||||||
|
[[ "$enabled" == *"$uuid"* ]] || continue
|
||||||
|
enabled="$(sed -e "s/'$uuid', //; s/, '$uuid'//; s/'$uuid'//" <<<"$enabled")"
|
||||||
|
[[ "$enabled" == "[]" ]] && enabled="@as []"
|
||||||
|
gsettings set org.gnome.shell enabled-extensions "$enabled"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
gnome_extras_release() {
|
||||||
|
# Called when the SteamOS conversion or the GNOME theme was turned off, after its own undoing. While the other one is
|
||||||
|
# still on, the extensions stay (and are enabled again: the theme's undo puts back the list it found). When neither is:
|
||||||
|
# they are disabled, and the packages Steamify installed are removed (a failed removal, because something else needs a
|
||||||
|
# package, keeps it).
|
||||||
|
[[ "$(desktop_kind)" == gnome ]] || return 0
|
||||||
|
if gaming_status || gnometheme_status; then gnome_extensions_enable; return 0; fi
|
||||||
|
gnome_extensions_disable
|
||||||
|
local p list="$STATE_DIR/gnomeextras.list"
|
||||||
|
for p in "${GNOME_EXTRA_PKGS[@]}"; do
|
||||||
|
grep -qxF "$p" "$list" 2>/dev/null || continue
|
||||||
|
pacman -Q "$p" >/dev/null 2>&1 || continue
|
||||||
|
sudo pacman -R --noconfirm "$p" >/dev/null 2>&1 || info "Keeping $p installed (another package needs it)."
|
||||||
|
done
|
||||||
|
rm -f "$list"
|
||||||
|
}
|
||||||
+60
-3
@@ -91,16 +91,20 @@ gnometheme_shell() {
|
|||||||
# The top bar and dash colors (the Steamify Vapor extension), and the dock beside it.
|
# The top bar and dash colors (the Steamify Vapor extension), and the dock beside it.
|
||||||
gnometheme_extensions_install
|
gnometheme_extensions_install
|
||||||
gnometheme_backgrounds
|
gnometheme_backgrounds
|
||||||
# Like Ubuntu's dock: on the left, always there; its look is Ubuntu's own, left as it is. Its shape (a
|
# Ubuntu's dock, always there, at the bottom (Ubuntu puts it on the left; on a wide screen the bottom is where the eye
|
||||||
# panel to the screen edge or floating) is left to the user: Dock Settings.
|
# and the pointer are); its look is Ubuntu's own, left as it is. Its shape (a panel to the screen edge or floating)
|
||||||
|
# is left to the user: Dock Settings.
|
||||||
local d=org.gnome.shell.extensions.dash-to-dock
|
local d=org.gnome.shell.extensions.dash-to-dock
|
||||||
gset gnometheme $d dock-position "'LEFT'" || true
|
gset gnometheme $d dock-position "'BOTTOM'" || true
|
||||||
gset gnometheme $d dock-fixed true || true
|
gset gnometheme $d dock-fixed true || true
|
||||||
gset gnometheme $d running-indicator-style "'DOTS'" || true
|
gset gnometheme $d running-indicator-style "'DOTS'" || true
|
||||||
gset gnometheme $d click-action "'minimize-or-previews'" || true
|
gset gnometheme $d click-action "'minimize-or-previews'" || true
|
||||||
# Trash is in the dock, not on the desktop (Ubuntu does the same).
|
# Trash is in the dock, not on the desktop (Ubuntu does the same).
|
||||||
gset gnometheme org.gnome.shell.extensions.ding show-trash false || true
|
gset gnometheme org.gnome.shell.extensions.ding show-trash false || true
|
||||||
gset gnometheme $d show-trash true || true
|
gset gnometheme $d show-trash true || true
|
||||||
|
# Desktop icons from the top right, like Ubuntu's and macOS's desktops (Desktop Icons NG fills from the corner it starts at).
|
||||||
|
gset gnometheme org.gnome.shell.extensions.ding start-corner "'top-right'" || true
|
||||||
|
gnometheme_desktop_icons_reset
|
||||||
local uuid enabled
|
local uuid enabled
|
||||||
for uuid in "${GNOME_THEME_EXTENSIONS[@]}"; do
|
for uuid in "${GNOME_THEME_EXTENSIONS[@]}"; do
|
||||||
enabled="$(gs get org.gnome.shell enabled-extensions 2>/dev/null)" || return 0
|
enabled="$(gs get org.gnome.shell enabled-extensions 2>/dev/null)" || return 0
|
||||||
@@ -111,6 +115,42 @@ gnometheme_shell() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gnometheme_desktop_icons_reset() {
|
||||||
|
# Steamify's own launchers on the desktop were placed (and their spot saved) from the left corner: without a saved
|
||||||
|
# position Desktop Icons NG puts them where its start corner says, by name. Only these, never the user's files.
|
||||||
|
local dir f
|
||||||
|
dir="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")"
|
||||||
|
for f in "$dir/Return to Gaming Mode.desktop" "$dir/io.github.theupriser.Steamify.desktop" "$dir/steam.desktop"; do
|
||||||
|
[[ -e "$f" ]] && gio set -t unset "$f" metadata::nautilus-icon-position 2>/dev/null
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
gnometheme_extras_install() {
|
||||||
|
# The desktop icons and the tray icons of the Ubuntu-style look: Desktop Icons NG and AppIndicator (and Extension Manager
|
||||||
|
# for them), the same the SteamOS conversion needs (lib/desktop-shortcut.sh). Not fatal: the theme works without them.
|
||||||
|
gnome_extras_note_missing
|
||||||
|
sudo pacman -S --needed --noconfirm "${GNOME_EXTRA_PKGS[@]}" >/dev/null 2>&1 ||
|
||||||
|
{ warn "Couldn't install Desktop Icons NG and AppIndicator: the desktop and the tray show no icons."; return 0; }
|
||||||
|
gnome_extensions_enable
|
||||||
|
}
|
||||||
|
|
||||||
|
gnometheme_relogin_needed() {
|
||||||
|
# A GNOME session is running and this run changed the theme: GNOME Shell on Wayland can't be restarted in place, so
|
||||||
|
# the new extensions, the dock and the Settings panel show after the user logs in again.
|
||||||
|
[[ " $* " == *" gnometheme "* ]] && pgrep -u "$(id -u)" -x gnome-shell >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
gnometheme_relogin() {
|
||||||
|
# End the GNOME session. With GDM autologin set up by the conversion, steamify-gdm-relogin logs the user straight back
|
||||||
|
# into the session they were in (GDM takes it from AccountsService; the session is not changed here, unlike
|
||||||
|
# steamos-session-select, which would make GNOME the one gaming mode's boot goes back to). Without that helper there
|
||||||
|
# is no autologin: a plain logout, and the user logs in again.
|
||||||
|
local helper=/usr/local/libexec/steamify-gdm-relogin
|
||||||
|
if [[ -x "$helper" ]] && sudo -n "$helper" "${XDG_SESSION_DESKTOP:-gnome}"; then return 0; fi
|
||||||
|
gnome-session-quit --logout --no-prompt
|
||||||
|
}
|
||||||
|
|
||||||
gnometheme_settings_install() {
|
gnometheme_settings_install() {
|
||||||
# The prebuilt GNOME Settings with the Desktop panel, replacing the stock one. Never fatal: the theme works without the
|
# The prebuilt GNOME Settings with the Desktop panel, replacing the stock one. Never fatal: the theme works without the
|
||||||
# panel, so a failed download or install keeps the stock Settings and says so.
|
# panel, so a failed download or install keeps the stock Settings and says so.
|
||||||
@@ -170,8 +210,11 @@ gnometheme_enable() {
|
|||||||
fi
|
fi
|
||||||
{ echo "$GNOME_THEME_MARK"; patch_file steamify-gnome-gtk4.css; } > "$GNOME_THEME_CSS"
|
{ echo "$GNOME_THEME_MARK"; patch_file steamify-gnome-gtk4.css; } > "$GNOME_THEME_CSS"
|
||||||
gnometheme_shell
|
gnometheme_shell
|
||||||
|
gnometheme_extras_install
|
||||||
gnometheme_settings_install
|
gnometheme_settings_install
|
||||||
ok "SteamOS theme for GNOME on (apps pick up the colors when they start again)."
|
ok "SteamOS theme for GNOME on (apps pick up the colors when they start again)."
|
||||||
|
# (GNOME Shell on Wayland can't restart in place: the app offers "Restart GNOME", which is this.)
|
||||||
|
gnometheme_relogin_needed gnometheme && info "Log out and back in for the dock, the extensions and the Settings panel to show."
|
||||||
}
|
}
|
||||||
|
|
||||||
gnometheme_disable() {
|
gnometheme_disable() {
|
||||||
@@ -180,6 +223,18 @@ gnometheme_disable() {
|
|||||||
# (The Dock/Desktop Icons/Tiling Settings launchers of earlier prototypes.)
|
# (The Dock/Desktop Icons/Tiling Settings launchers of earlier prototypes.)
|
||||||
rm -f "${XDG_DATA_HOME:-$HOME/.local/share}"/applications/steamify-{dock,icons,tiling}-settings.desktop \
|
rm -f "${XDG_DATA_HOME:-$HOME/.local/share}"/applications/steamify-{dock,icons,tiling}-settings.desktop \
|
||||||
"${XDG_DATA_HOME:-$HOME/.local/share}/gnome-background-properties/steamify-steamos.xml"
|
"${XDG_DATA_HOME:-$HOME/.local/share}/gnome-background-properties/steamify-steamos.xml"
|
||||||
|
# The schemas of the dock and of tiling that were copied next to the user's own for GNOME Settings' panel
|
||||||
|
# (gnometheme_extensions_install): they go with the extensions, or settings schemas of nothing are left behind.
|
||||||
|
local schemas="${XDG_DATA_HOME:-$HOME/.local/share}/glib-2.0/schemas" ext f
|
||||||
|
for ext in ubuntu-dock@ubuntu.com tiling-assistant@ubuntu.com; do
|
||||||
|
for f in "$GNOME_USER_EXTENSIONS/$ext"/schemas/*.gschema.xml; do
|
||||||
|
[[ -e "$f" ]] && rm -f "$schemas/$(basename "$f")"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
# (Also by name: the extension folders may be gone already.)
|
||||||
|
rm -f "$schemas"/org.gnome.shell.extensions.{dash-to-dock,tiling-assistant}.gschema.xml
|
||||||
|
if compgen -G "$schemas/*.gschema.xml" >/dev/null; then glib-compile-schemas "$schemas" 2>/dev/null
|
||||||
|
else rm -f "$schemas/gschemas.compiled"; rmdir "$schemas" 2>/dev/null; fi
|
||||||
rm -rf "$GNOME_USER_EXTENSIONS/steamify-vapor@steamify.github.io" "$GNOME_USER_EXTENSIONS/ubuntu-dock@ubuntu.com" "$GNOME_USER_EXTENSIONS/tiling-assistant@ubuntu.com"
|
rm -rf "$GNOME_USER_EXTENSIONS/steamify-vapor@steamify.github.io" "$GNOME_USER_EXTENSIONS/ubuntu-dock@ubuntu.com" "$GNOME_USER_EXTENSIONS/tiling-assistant@ubuntu.com"
|
||||||
if [[ -f "$STATE_DIR/gnometheme-gtk4.css" ]]; then
|
if [[ -f "$STATE_DIR/gnometheme-gtk4.css" ]]; then
|
||||||
mv -f "$STATE_DIR/gnometheme-gtk4.css" "$GNOME_THEME_CSS"
|
mv -f "$STATE_DIR/gnometheme-gtk4.css" "$GNOME_THEME_CSS"
|
||||||
@@ -197,5 +252,7 @@ gnometheme_disable() {
|
|||||||
info "Keeping GNOME Settings with the Desktop panel (the stock one couldn't be installed)."
|
info "Keeping GNOME Settings with the Desktop panel (the stock one couldn't be installed)."
|
||||||
fi
|
fi
|
||||||
state_clear gnometheme
|
state_clear gnometheme
|
||||||
|
# (After the state is cleared and the stylesheet is gone: the theme itself is off for gnome_extras_release's check.)
|
||||||
|
gnome_extras_release
|
||||||
ok "Previous GNOME look restored."
|
ok "Previous GNOME look restored."
|
||||||
}
|
}
|
||||||
@@ -153,6 +153,7 @@ gaming_disable() {
|
|||||||
os_name_disable
|
os_name_disable
|
||||||
# NVIDIA with single user mode still on: nothing else logs in by itself any more.
|
# NVIDIA with single user mode still on: nothing else logs in by itself any more.
|
||||||
nvidia_present && single_status && single_login_enable
|
nvidia_present && single_status && single_login_enable
|
||||||
|
gnome_extras_release
|
||||||
ok "The PC boots to the normal login screen again (from the next boot)."
|
ok "The PC boots to the normal login screen again (from the next boot)."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ NO_PRESELECT=(boot silent nvsilent cec kpin hdmi extended_controller_support)
|
|||||||
# FEATURE_BASELINE.
|
# FEATURE_BASELINE.
|
||||||
FEATURE_BASELINE=2.1.0
|
FEATURE_BASELINE=2.1.0
|
||||||
declare -A FEATURE_VERSION=(
|
declare -A FEATURE_VERSION=(
|
||||||
[gaming]=2.9.0 [boot]=2.1.0 [silent]=2.11.0 [nvidia]=2.12.0 [bigpicture]=2.10.0 [nvsilent]=2.11.0 [theme]=2.1.0 [gnometheme]=2.12.0 [glyphs]=2.1.0 [single]=2.1.0
|
[gaming]=2.9.0 [boot]=2.1.0 [silent]=2.11.0 [nvidia]=2.12.0 [bigpicture]=2.10.0 [nvsilent]=2.11.0 [theme]=2.1.0 [gnometheme]=2.13.0 [glyphs]=2.1.0 [single]=2.1.0
|
||||||
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1 [extended_controller_support]=2.10.0
|
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1 [extended_controller_support]=2.10.0
|
||||||
[kpin]=2.1.0 [hdmi]=2.1.0
|
[kpin]=2.1.0 [hdmi]=2.1.0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ install_required_packages() {
|
|||||||
|
|
||||||
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
||||||
python_hid_shim_ensure || return 1
|
python_hid_shim_ensure || return 1
|
||||||
|
# (What the GNOME extensions need is noted first: turning everything off removes what Steamify installed.)
|
||||||
|
[[ "$(desktop_kind)" == gnome ]] && gnome_extras_note_missing
|
||||||
info "Installing missing packages: ${MISSING[*]}"
|
info "Installing missing packages: ${MISSING[*]}"
|
||||||
sudo pacman -S --needed --noconfirm "${MISSING[@]}" || { err "Package installation failed."; return 1; }
|
sudo pacman -S --needed --noconfirm "${MISSING[@]}" || { err "Package installation failed."; return 1; }
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ notify_enable() {
|
|||||||
info "Adding update notifications..."
|
info "Adding update notifications..."
|
||||||
# PySide6 for the tray icon, notify-send for the notification's buttons.
|
# PySide6 for the tray icon, notify-send for the notification's buttons.
|
||||||
python3 -c 'import PySide6.QtWidgets' 2>/dev/null || missing+=(pyside6)
|
python3 -c 'import PySide6.QtWidgets' 2>/dev/null || missing+=(pyside6)
|
||||||
|
# (Its icons are SVGs, and Qt needs its SVG plugin for those.)
|
||||||
|
pacman -Q qt6-svg >/dev/null 2>&1 || missing+=(qt6-svg)
|
||||||
command -v notify-send >/dev/null || missing+=(libnotify)
|
command -v notify-send >/dev/null || missing+=(libnotify)
|
||||||
if ((${#missing[@]})); then
|
if ((${#missing[@]})); then
|
||||||
sudo pacman -S --needed --noconfirm "${missing[@]}" ||
|
sudo pacman -S --needed --noconfirm "${missing[@]}" ||
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ EOF
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Installed by Steamify CachyOS: start the newest release of its app.
|
# Installed by Steamify CachyOS: start the newest release of its app.
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
if [[ "\${1:-}" != --in-terminal ]] && ! python3 -c 'import PySide6.QtQml' 2>/dev/null; then
|
if [[ "\${1:-}" != --in-terminal ]] && { ! python3 -c 'import PySide6.QtQml' 2>/dev/null || ! pacman -Q qt6-svg >/dev/null 2>&1; }; then
|
||||||
exec $terminal "\$0" --in-terminal
|
exec $terminal "\$0" --in-terminal
|
||||||
fi
|
fi
|
||||||
if ! curl -fsSL --max-time 30 "$WIZARD_APP_URL" | bash; then
|
if ! curl -fsSL --max-time 30 "$WIZARD_APP_URL" | bash; then
|
||||||
@@ -110,7 +110,14 @@ EOF
|
|||||||
# The icon comes with the release; without it, Steam's own icon.
|
# The icon comes with the release; without it, Steam's own icon.
|
||||||
local icon=steam tmp
|
local icon=steam tmp
|
||||||
tmp="$(mktemp)"
|
tmp="$(mktemp)"
|
||||||
if curl -fsSL --max-time 20 "$WIZARD_RELEASE/steam-gaming-settings.svg" -o "$tmp" && grep -q '<svg' "$tmp"; then
|
local theme="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor"
|
||||||
|
# A PNG, by name, first: GNOME's dock can't always draw an SVG (blank icon, "Could not load a pixbuf from icon theme").
|
||||||
|
# (Releases before 2.13.0 only have the SVG.)
|
||||||
|
if curl -fsSL --max-time 20 "$WIZARD_RELEASE/steam-gaming-settings.png" -o "$tmp" && head -c 8 "$tmp" | grep -q PNG; then
|
||||||
|
install -D -m 644 "$tmp" "$theme/256x256/apps/io.github.theupriser.Steamify.png"
|
||||||
|
icon=io.github.theupriser.Steamify
|
||||||
|
gtk-update-icon-cache -q -f -t "$theme" 2>/dev/null || true
|
||||||
|
elif curl -fsSL --max-time 20 "$WIZARD_RELEASE/steam-gaming-settings.svg" -o "$tmp" && grep -q '<svg' "$tmp"; then
|
||||||
install -D -m 644 "$tmp" "$WIZARD_ICON"
|
install -D -m 644 "$tmp" "$WIZARD_ICON"
|
||||||
# The full path: GNOME Shell's dock doesn't find a name in the user's icon folder (blank icon), and every desktop takes a path.
|
# The full path: GNOME Shell's dock doesn't find a name in the user's icon folder (blank icon), and every desktop takes a path.
|
||||||
icon="$WIZARD_ICON"
|
icon="$WIZARD_ICON"
|
||||||
|
|||||||
@@ -6,11 +6,36 @@
|
|||||||
# ("A graphical session is already running!"): so the user is ended first,
|
# ("A graphical session is already running!"): so the user is ended first,
|
||||||
# then GDM restarted. That work runs in its own transient unit, because
|
# then GDM restarted. That work runs in its own transient unit, because
|
||||||
# ending the user kills this process too.
|
# ending the user kills this process too.
|
||||||
|
#
|
||||||
|
# An optional session id as the argument ("gnome"): that session is logged in
|
||||||
|
# for this time only. The session in AccountsService (what the next boot goes
|
||||||
|
# to: gaming mode after the SteamOS conversion) is put back once the new
|
||||||
|
# session is up.
|
||||||
if [[ "$1" != --work ]]; then
|
if [[ "$1" != --work ]]; then
|
||||||
[[ -n "${SUDO_USER:-}" ]] || exit 1
|
[[ -n "${SUDO_USER:-}" ]] || exit 1
|
||||||
exec systemd-run --no-block --collect --unit=steamify-gdm-relogin "$0" --work "$SUDO_USER"
|
exec systemd-run --no-block --collect --unit=steamify-gdm-relogin "$0" --work "$SUDO_USER" "${1:-}"
|
||||||
fi
|
fi
|
||||||
USER_NAME="$2"
|
USER_NAME="$2"
|
||||||
|
SESSION="$3"
|
||||||
|
ACCOUNT="/var/lib/AccountsService/users/$USER_NAME"
|
||||||
|
|
||||||
|
# Session= and XSession= of the user, as GDM reads them at the next login.
|
||||||
|
get_session() { sed -n "s/^$1=//p" "$ACCOUNT" 2>/dev/null | head -1; }
|
||||||
|
set_session() {
|
||||||
|
local key
|
||||||
|
touch "$ACCOUNT"
|
||||||
|
grep -q '^\[User\]' "$ACCOUNT" || echo "[User]" >> "$ACCOUNT"
|
||||||
|
for key in Session XSession; do
|
||||||
|
if grep -q "^$key=" "$ACCOUNT"; then sed -i "s|^$key=.*|$key=$1|" "$ACCOUNT"
|
||||||
|
else sed -i "/^\[User\]/a $key=$1" "$ACCOUNT"; fi
|
||||||
|
done
|
||||||
|
systemctl restart accounts-daemon 2>/dev/null || true
|
||||||
|
}
|
||||||
|
if [[ -n "$SESSION" ]]; then
|
||||||
|
OLD_SESSION="$(get_session Session)"; OLD_XSESSION="$(get_session XSession)"
|
||||||
|
set_session "${SESSION%.desktop}"
|
||||||
|
fi
|
||||||
|
|
||||||
# GDM is stopped first, so its login screen doesn't show while the old user
|
# GDM is stopped first, so its login screen doesn't show while the old user
|
||||||
# manager shuts down; a new login right away fails ("A graphical session is
|
# manager shuts down; a new login right away fails ("A graphical session is
|
||||||
# already running!", or the session dies at once), so wait until it is gone.
|
# already running!", or the session dies at once), so wait until it is gone.
|
||||||
@@ -20,3 +45,14 @@ loginctl terminate-user "$USER_NAME"
|
|||||||
USER_RUNTIME="/run/user/$(id -u "$USER_NAME")"
|
USER_RUNTIME="/run/user/$(id -u "$USER_NAME")"
|
||||||
for _ in $(seq 120); do [[ -d "$USER_RUNTIME" ]] || break; sleep 0.25; done
|
for _ in $(seq 120); do [[ -d "$USER_RUNTIME" ]] || break; sleep 0.25; done
|
||||||
systemctl start gdm.service
|
systemctl start gdm.service
|
||||||
|
|
||||||
|
if [[ -n "$SESSION" ]]; then
|
||||||
|
# The new session has read what it logs in to once its user manager runs; then the next boot's session goes back.
|
||||||
|
for _ in $(seq 120); do [[ -d "$USER_RUNTIME" ]] && break; sleep 0.25; done
|
||||||
|
sleep 8
|
||||||
|
if [[ -n "$OLD_SESSION" ]]; then
|
||||||
|
sed -i "s|^Session=.*|Session=$OLD_SESSION|" "$ACCOUNT"
|
||||||
|
if [[ -n "$OLD_XSESSION" ]]; then sed -i "s|^XSession=.*|XSession=$OLD_XSESSION|" "$ACCOUNT"; fi
|
||||||
|
systemctl restart accounts-daemon 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
# Release version, see CHANGELOG.md.
|
# Release version, see CHANGELOG.md.
|
||||||
VERSION=2.12.0
|
VERSION=2.13.0
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -18,6 +18,7 @@ Item {
|
|||||||
property var steps: ({}) // id -> "wait"|"run"|"ok"|"fail"
|
property var steps: ({}) // id -> "wait"|"run"|"ok"|"fail"
|
||||||
property var failed: []
|
property var failed: []
|
||||||
property bool restartNeeded: false
|
property bool restartNeeded: false
|
||||||
|
property bool reloginNeeded: false // GNOME loads the new theme's extensions at the next login
|
||||||
// Review & apply only when something would change; "Re-apply what's on"
|
// Review & apply only when something would change; "Re-apply what's on"
|
||||||
// is for when nothing did.
|
// is for when nothing did.
|
||||||
readonly property bool canApply: computePlan().length > 0
|
readonly property bool canApply: computePlan().length > 0
|
||||||
@@ -123,7 +124,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Password and apply ---
|
// --- Password and apply ---
|
||||||
function resetRun() { steps = {}; failed = []; restartNeeded = false; runError = ""; doneCount = 0; logModel.clear(); }
|
function resetRun() { steps = {}; failed = []; restartNeeded = false; reloginNeeded = false; runError = ""; doneCount = 0; logModel.clear(); }
|
||||||
function startApply(password) {
|
function startApply(password) {
|
||||||
resetRun();
|
resetRun();
|
||||||
var s = {};
|
var s = {};
|
||||||
@@ -203,7 +204,7 @@ Item {
|
|||||||
// A successful BIOS check ends with bios-ready instead, keeping
|
// A successful BIOS check ends with bios-ready instead, keeping
|
||||||
// the password for the flash.
|
// the password for the flash.
|
||||||
app.sessionPassword = "";
|
app.sessionPassword = "";
|
||||||
app.failed = ev.failed || []; app.restartNeeded = !!ev.restart;
|
app.failed = ev.failed || []; app.restartNeeded = !!ev.restart; app.reloginNeeded = !!ev.relogin;
|
||||||
app.runError = app.errorText(ev.error);
|
app.runError = app.errorText(ev.error);
|
||||||
app.screen = "done";
|
app.screen = "done";
|
||||||
}
|
}
|
||||||
@@ -249,6 +250,7 @@ Item {
|
|||||||
else if (a === "release") { holding = false; if (holdProgress < 1) holdProgress = 0; }
|
else if (a === "release") { holding = false; if (holdProgress < 1) holdProgress = 0; }
|
||||||
} else if (screen === "done") {
|
} else if (screen === "done") {
|
||||||
if (a === "accept" && restartNeeded) backend.restart();
|
if (a === "accept" && restartNeeded) backend.restart();
|
||||||
|
else if (a === "accept" && reloginNeeded) backend.restartGnome();
|
||||||
else if (a === "back" || a === "accept") backToMenu();
|
else if (a === "back" || a === "accept") backToMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-2
@@ -7,9 +7,24 @@ import QtQuick.Controls.Basic
|
|||||||
Item {
|
Item {
|
||||||
required property AppState app
|
required property AppState app
|
||||||
readonly property bool problem: app.failed.length > 0 || app.runError !== ""
|
readonly property bool problem: app.failed.length > 0 || app.runError !== ""
|
||||||
|
// GNOME Shell on Wayland can't restart in place (it is the compositor too), so what a KDE run does for plasmashell is a
|
||||||
|
// new login here: started by itself after a countdown, unless the run needs a reboot anyway (which does the same).
|
||||||
|
readonly property bool relogin: app.reloginNeeded && !app.restartNeeded && !problem
|
||||||
|
property int countdown: 10
|
||||||
|
property bool cancelled: false
|
||||||
|
property bool fired: false
|
||||||
|
readonly property bool counting: relogin && !cancelled && !fired
|
||||||
|
onVisibleChanged: if (visible) { countdown = 10; cancelled = false; fired = false; }
|
||||||
|
function reloginNow() { fired = true; app.backend.restartGnome(); }
|
||||||
|
Timer {
|
||||||
|
interval: 1000; repeat: true; running: parent.visible && parent.counting
|
||||||
|
onTriggered: { parent.countdown -= 1; if (parent.countdown <= 0) parent.reloginNow(); }
|
||||||
|
}
|
||||||
readonly property string message: {
|
readonly property string message: {
|
||||||
if (app.runError) return app.runError;
|
if (app.runError) return app.runError;
|
||||||
if (!app.biosRun) return app.plan.length + (app.plan.length === 1 ? " change" : " changes") + " applied." + (app.restartNeeded ? " Some take effect after a restart." : "");
|
if (!app.biosRun) return app.plan.length + (app.plan.length === 1 ? " change" : " changes") + " applied." + (app.restartNeeded ? " Some take effect after a restart." : "")
|
||||||
|
+ (counting ? " Restarting GNOME in " + countdown + " s, so it loads the new dock, extensions and Settings panel."
|
||||||
|
: (relogin ? " GNOME shows the dock, extensions and Settings panel after you log in again." : ""));
|
||||||
if (app.failed.length) return "The BIOS was not changed.";
|
if (app.failed.length) return "The BIOS was not changed.";
|
||||||
return (app.bios && app.bios.dryRun ? "Dry run: nothing was flashed. " : "BIOS " + (app.biosInfo.newest || "") + " is staged and is written during the restart. ")
|
return (app.bios && app.bios.dryRun ? "Dry run: nothing was flashed. " : "BIOS " + (app.biosInfo.newest || "") + " is staged and is written during the restart. ")
|
||||||
+ "Keep the power on and don't touch the machine until it has fully started again, even if the screen stays black.";
|
+ "Keep the power on and don't touch the machine until it has fully started again, even if the screen stays black.";
|
||||||
@@ -33,6 +48,8 @@ Item {
|
|||||||
delegate: Text { required property string line; width: details.width - 12; text: line; color: "#aab5c4"; font.family: Theme.mono; font.pixelSize: 13; wrapMode: Text.WrapAnywhere } } }
|
delegate: Text { required property string line; width: details.width - 12; text: line; color: "#aab5c4"; font.family: Theme.mono; font.pixelSize: 13; wrapMode: Text.WrapAnywhere } } }
|
||||||
Row { anchors.horizontalCenter: parent.horizontalCenter; spacing: 14; topPadding: 8
|
Row { anchors.horizontalCenter: parent.horizontalCenter; spacing: 14; topPadding: 8
|
||||||
Btn { k: Input.g.back; text: "Back to the menu"; height: 52; onClicked: app.act("back") }
|
Btn { k: Input.g.back; text: "Back to the menu"; height: 52; onClicked: app.act("back") }
|
||||||
Btn { visible: app.restartNeeded; k: Input.g.ok; text: "Restart now"; primary: true; height: 52; onClicked: app.backend.restart() } }
|
Btn { visible: app.restartNeeded; k: Input.g.ok; text: "Restart now"; primary: true; height: 52; onClicked: app.backend.restart() }
|
||||||
|
Btn { visible: relogin; k: Input.g.ok; text: counting ? "Restart GNOME now" : "Restart GNOME"; primary: true; height: 52; onClicked: reloginNow() }
|
||||||
|
Btn { visible: counting; text: "Cancel"; height: 52; onClicked: cancelled = true } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-1
@@ -36,7 +36,11 @@ ApplicationWindow {
|
|||||||
// own shape, so the bars reach the edges and the content fills it.
|
// own shape, so the bars reach the edges and the content fills it.
|
||||||
Item {
|
Item {
|
||||||
id: stage
|
id: stage
|
||||||
readonly property real k: Math.min(win.width / 1280, win.height / 720)
|
// On a desktop (a window, however large) the UI keeps the desktop's own scale: 1 here is one logical pixel, which Qt
|
||||||
|
// multiplies by the scale of GNOME or KDE, like any other app (a 1440p or ultrawide monitor would otherwise show
|
||||||
|
// everything twice as big). Only a window smaller than the layout shrinks it. The TV mode (--fullscreen, gamescope)
|
||||||
|
// scales to the screen: it is read from the couch.
|
||||||
|
readonly property real k: Math.min(win.width / 1280, win.height / 720, win.fullscreen ? Infinity : 1)
|
||||||
width: win.width / k; height: win.height / k
|
width: win.width / k; height: win.height / k
|
||||||
transformOrigin: Item.TopLeft
|
transformOrigin: Item.TopLeft
|
||||||
scale: k
|
scale: k
|
||||||
|
|||||||
+9
-3
@@ -31,7 +31,9 @@ Item {
|
|||||||
color: row.selected ? Theme.cardSel : Theme.card
|
color: row.selected ? Theme.cardSel : Theme.card
|
||||||
border.width: row.selected ? 2 : 0; border.color: Theme.accent
|
border.width: row.selected ? 2 : 0; border.color: Theme.accent
|
||||||
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: { Input.type = "keyboard"; if (row.selected) app.act("accept"); else app.sel = row.rowIndex; } }
|
// A click on the row only selects it; the switch, the Gaming/Desktop buttons and the BIOS button act on their own
|
||||||
|
// click (below), selecting the row too.
|
||||||
|
onClicked: { Input.type = "keyboard"; app.sel = row.rowIndex; } }
|
||||||
|
|
||||||
Text { visible: !!row.it.parent; x: 20; anchors.verticalCenter: parent.verticalCenter; text: "└"; color: "#56627a"; font.pixelSize: 18 }
|
Text { visible: !!row.it.parent; x: 20; anchors.verticalCenter: parent.verticalCenter; text: "└"; color: "#56627a"; font.pixelSize: 18 }
|
||||||
Column {
|
Column {
|
||||||
@@ -67,14 +69,18 @@ Item {
|
|||||||
Rectangle { id: sw; visible: row.it.kind === "toggle"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
|
Rectangle { id: sw; visible: row.it.kind === "toggle"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
|
||||||
width: 46; height: 26; radius: 13; color: row.on ? Theme.accent : "#343f50"
|
width: 46; height: 26; radius: 13; color: row.on ? Theme.accent : "#343f50"
|
||||||
Behavior on color { ColorAnimation { duration: 120 } }
|
Behavior on color { ColorAnimation { duration: 120 } }
|
||||||
Rectangle { width: 20; height: 20; radius: 10; color: "#f4f7fb"; y: 3; x: row.on ? 23 : 3; Behavior on x { NumberAnimation { duration: 120 } } } }
|
Rectangle { width: 20; height: 20; radius: 10; color: "#f4f7fb"; y: 3; x: row.on ? 23 : 3; Behavior on x { NumberAnimation { duration: 120 } } }
|
||||||
|
MouseArea { anchors.fill: parent; anchors.margins: -6; cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: { Input.type = "keyboard"; app.sel = row.rowIndex; app.act("accept"); } } }
|
||||||
Text { visible: row.it.kind === "toggle"; anchors.right: sw.left; anchors.rightMargin: 12; anchors.verticalCenter: parent.verticalCenter
|
Text { visible: row.it.kind === "toggle"; anchors.right: sw.left; anchors.rightMargin: 12; anchors.verticalCenter: parent.verticalCenter
|
||||||
text: row.it.on ? "now on" : "now off"; color: row.it.on ? Theme.good : Theme.faint; font.family: Theme.mono; font.pixelSize: 12 }
|
text: row.it.on ? "now on" : "now off"; color: row.it.on ? Theme.good : Theme.faint; font.family: Theme.mono; font.pixelSize: 12 }
|
||||||
// action (Update BIOS)
|
// action (Update BIOS)
|
||||||
Rectangle { visible: row.it.kind === "action"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
|
Rectangle { visible: row.it.kind === "action"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
|
||||||
width: at.implicitWidth + 24; height: 30; radius: 8; color: Theme.warnBg
|
width: at.implicitWidth + 24; height: 30; radius: 8; color: Theme.warnBg
|
||||||
Text { id: at; anchors.centerIn: parent; color: Theme.warn; font.family: Theme.body; font.pixelSize: 13; font.weight: Font.DemiBold
|
Text { id: at; anchors.centerIn: parent; color: Theme.warn; font.family: Theme.body; font.pixelSize: 13; font.weight: Font.DemiBold
|
||||||
text: app.biosChecking ? "Checking…" : app.bios && app.bios.selectable ? "Update…" : (app.bios && app.bios.newest ? "Up to date" : "Unavailable") } }
|
text: app.biosChecking ? "Checking…" : app.bios && app.bios.selectable ? "Update…" : (app.bios && app.bios.newest ? "Up to date" : "Unavailable") }
|
||||||
|
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: { Input.type = "keyboard"; app.sel = row.rowIndex; app.act("accept"); } } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+19
-4
@@ -47,10 +47,14 @@ rm -rf "$DEST.new"; mv "$tmp/app" "$DEST.new"
|
|||||||
rm -rf "$DEST"; mv "$DEST.new" "$DEST"
|
rm -rf "$DEST"; mv "$DEST.new" "$DEST"
|
||||||
say "Installed to $DEST ($(grep -m1 -oP '^VERSION=\K.*' "$DEST/steamify.sh"))."
|
say "Installed to $DEST ($(grep -m1 -oP '^VERSION=\K.*' "$DEST/steamify.sh"))."
|
||||||
|
|
||||||
if ! python3 -c 'import PySide6.QtQml' 2>/dev/null; then
|
missing=()
|
||||||
say "The app needs PySide6 (Qt for Python); installing it..."
|
python3 -c 'import PySide6.QtQml' 2>/dev/null || missing+=(pyside6)
|
||||||
|
# The app's logo is an SVG: Qt needs its SVG plugin for it, and pyside6 doesn't pull it in.
|
||||||
|
pacman -Q qt6-svg >/dev/null 2>&1 || missing+=(qt6-svg)
|
||||||
|
if ((${#missing[@]})); then
|
||||||
|
say "The app needs ${missing[*]} (Qt for Python and its SVG support); installing..."
|
||||||
# Piped in via curl, stdin isn't the terminal: sudo asks on it anyway.
|
# Piped in via curl, stdin isn't the terminal: sudo asks on it anyway.
|
||||||
sudo pacman -S --needed --noconfirm pyside6 </dev/tty || die "Installing pyside6 failed."
|
sudo pacman -S --needed --noconfirm "${missing[@]}" </dev/tty || die "Installing ${missing[*]} failed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Launcher entry (its id also names the app to the desktop portal). The
|
# Launcher entry (its id also names the app to the desktop portal). The
|
||||||
@@ -58,6 +62,17 @@ fi
|
|||||||
# release: left alone.
|
# release: left alone.
|
||||||
mkdir -p "$APPS"
|
mkdir -p "$APPS"
|
||||||
rm -f "$APPS/steamify-ui.desktop" # its name until 2.12.0
|
rm -f "$APPS/steamify-ui.desktop" # its name until 2.12.0
|
||||||
|
# The icon by name, from the user's icon theme, as a PNG: GNOME's dock can't always draw an SVG (blank icon: "Could not load a
|
||||||
|
# pixbuf from icon theme"), and a file path to one fails the same way.
|
||||||
|
ICON_NAME=io.github.theupriser.Steamify
|
||||||
|
ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor"
|
||||||
|
if [[ -f "$DEST/assets/steam-gaming-settings.png" ]]; then
|
||||||
|
install -D -m 644 "$DEST/assets/steam-gaming-settings.png" "$ICON_DIR/256x256/apps/$ICON_NAME.png"
|
||||||
|
gtk-update-icon-cache -q -f -t "$ICON_DIR" 2>/dev/null || true
|
||||||
|
ICON="$ICON_NAME"
|
||||||
|
else
|
||||||
|
ICON="$DEST/assets/steam-gaming-settings.svg"
|
||||||
|
fi
|
||||||
grep -q '^X-Steamify-Shortcut=true' "$APPS/io.github.theupriser.Steamify.desktop" 2>/dev/null ||
|
grep -q '^X-Steamify-Shortcut=true' "$APPS/io.github.theupriser.Steamify.desktop" 2>/dev/null ||
|
||||||
cat > "$APPS/io.github.theupriser.Steamify.desktop" << EOF
|
cat > "$APPS/io.github.theupriser.Steamify.desktop" << EOF
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
@@ -65,7 +80,7 @@ Type=Application
|
|||||||
Name=Steamify CachyOS
|
Name=Steamify CachyOS
|
||||||
Comment=Turn this PC into a SteamOS-style console
|
Comment=Turn this PC into a SteamOS-style console
|
||||||
Exec=$DEST/ui/steamify-ui
|
Exec=$DEST/ui/steamify-ui
|
||||||
Icon=$DEST/assets/steam-gaming-settings.svg
|
Icon=$ICON
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Categories=Game;Settings;
|
Categories=Game;Settings;
|
||||||
StartupWMClass=io.github.theupriser.Steamify
|
StartupWMClass=io.github.theupriser.Steamify
|
||||||
|
|||||||
@@ -345,6 +345,18 @@ class Backend(QObject):
|
|||||||
def restart(self):
|
def restart(self):
|
||||||
QProcess.startDetached("systemctl", ["reboot"])
|
QProcess.startDetached("systemctl", ["reboot"])
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def restartGnome(self):
|
||||||
|
# GNOME Shell on Wayland can't restart in place: end the session. With GDM autologin (the SteamOS conversion)
|
||||||
|
# Steamify's helper logs the user straight back in; else a plain logout.
|
||||||
|
import subprocess
|
||||||
|
helper = "/usr/local/libexec/steamify-gdm-relogin"
|
||||||
|
# The session this one is, for this login only: the default (gaming mode, after the conversion) would log in there.
|
||||||
|
session = os.environ.get("XDG_SESSION_DESKTOP") or "gnome"
|
||||||
|
if os.access(helper, os.X_OK) and subprocess.run(["sudo", "-n", helper, session], capture_output=True).returncode == 0:
|
||||||
|
return
|
||||||
|
QProcess.startDetached("gnome-session-quit", ["--logout", "--no-prompt"])
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
if self._proc and self._proc.state() != QProcess.NotRunning:
|
if self._proc and self._proc.state() != QProcess.NotRunning:
|
||||||
self._proc.kill()
|
self._proc.kill()
|
||||||
|
|||||||
Reference in new issue
Block a user