Rewrite layout switcher in Nim #3

Merged
tio merged 8 commits from nim-rewrite into master 2023-12-26 00:08:43 +00:00
2 changed files with 147 additions and 60 deletions
Showing only changes of commit c60c17100b - Show all commits

View File

@ -1,60 +0,0 @@
#! /bin/bash
data=/usr/share/tromjaro-layout-switcher
icons=$data/icons
profiles=$data/profiles
enable-top-bar-integration() {
# Enable global menus
pacman -Qq vala-panel-appmenu-registrar ||
zensu SKIP_AUTOSNAP= pacman -S --noconfirm vala-panel-appmenu-registrar ||
{ notify-send 'Error' 'Failed installing vala-panel-appmenu-registrar !\nmake sure that you typed the password correctly or that you are not currently installing or updating your system\nEnabling the internet connection might solve the issue'; exit; }
pacman -Qq vala-panel-appmenu-registrar || exit
# Hide window borders when maximized
xfconf-query -c xfwm4 -p /general/borderless_maximize -n -t bool -s true
# Hide top bar of windows when maximized
xfconf-query -c xfwm4 -p /general/titleless_maximize -n -t bool -s true
# Put window buttons on left side
xfconf-query -c xfwm4 -p /general/button_layout -n -t string -s "CMH|"
}
disable-top-bar-integration() {
# Disable global menus
! pacman -Qq vala-panel-appmenu-registrar ||
zensu SKIP_AUTOSNAP= pacman -R --noconfirm vala-panel-appmenu-registrar ||
{ notify-send 'Error' 'Failed removing vala-panel-appmenu-registrar !\nmake sure that you typed the password correctly or that you are not currently installing or updating your system'; exit; }
pacman -Qq vala-panel-appmenu-registrar && exit
killall appmenu-registrar
# Hide window borders when maximized
xfconf-query -c xfwm4 -p /general/borderless_maximize -n -t bool -s true
# Don't hide top bar of windows when maximized
xfconf-query -c xfwm4 -p /general/titleless_maximize -n -t bool -s false
# Put window buttons on right side
xfconf-query -c xfwm4 -p /general/button_layout -n -t string -s "|HMC"
}
choice=$(
yad --no-buttons --center --keep-icon-size --separator='' --use-interp --title 'TROMjaro Layout Switcher' --text-align=center --text ' Please use the Panel Profiles to save your current configuration in case you did any manual changes, else you may lose them.
Changing to or from any layout that has global menus, will require your admin password.' --form --columns 3 \
--field=!"$icons/windows.png"!'Windows-Like (default)':BTN "kill -USR1 \$YAD_PID; echo -n 'Windows-Like'" \
--field=!"$icons/macos.png"!'MacOS-Like (experimental)':BTN "kill -USR1 \$YAD_PID; echo -n 'MacOS-Like'" \
--field=!"$icons/mx.png"!'MX-Like':BTN "kill -USR1 \$YAD_PID; echo -n 'MX-Like'" \
--field=!"$icons/gnome.png"!'Gnome-Like':BTN "kill -USR1 \$YAD_PID; echo -n 'Gnome-Like'" \
--field=!"$icons/unity.png"!'Unity-Like (experimental)':BTN "kill -USR1 \$YAD_PID; echo -n 'Unity-Like'" \
--field=!"$icons/topx.png"!'TopX-Like':BTN "kill -USR1 \$YAD_PID; echo -n 'TopX-Like'"
)
case "$choice" in
'Windows-Like'|'MX-Like'|'Gnome-Like'|'TopX-Like')
disable-top-bar-integration ;;
'Unity-Like'|'MacOS-Like')
enable-top-bar-integration ;;
*) exit ;;
esac
# Apply the XFCE panel profiles for the chosen layout
xfce4-panel-profiles load "$profiles/$choice.tar.bz2"
killall mate-hud && setsid -f /usr/lib/mate-hud/mate-hud
sleep 2.5 && notify-send "$choice layout was enabled"

147
layoutSwitcher.nim Normal file
View File

@ -0,0 +1,147 @@
from std/os import symlinkExists, getConfigDir, `/`, sleep
from std/envvars import existsEnv, getEnv, delEnv, putEnv
from std/options import Option, some, get, isNone
from std/strutils import toLowerAscii, split
import owlkettle, sharedModule
const
dataDir = "/usr/share/tromjaro-layout-switcher"
iconsDir = dataDir / "icons"
profilesDir = dataDir / "profiles"
# GTK CSS for changing the default icon size and shape of our layout buttons
gtkCSS = """
.layout-button > image {
-gtk-icon-transform: scale(19);
}
.layout-button {
min-height: 200px;
min-width: 300px;
}"""
appID = "com.tromjaro.LayoutSwitcher"
layoutsGrid = [
[ "Windows-Like (default)", "MacOS-Like (experimental)", "MX-Like" ],
[ "Gnome-Like", "Unity-Like (experimental)", "TopX-Like" ]
]
proc enableTopBarIntegration(): bool =
if not isGlobalMenuEnabled():
# Enable global menu
let exitCode = runCommand("/usr/bin/pkexec", ["/usr/bin/toggle-global-menu", "enable"])
case exitCode
of 0:
discard
of 126:
return false
of 127:
sendNotification(appID, "Layout Switcher", "Authentication failed!")
return false
else:
sendNotification(appID, "Failed installing global menu!", "Make sure that you are not currently installing any apps or updating the system.\nEnabling internet connection might solve the issue.")
return false
# Hide window borders when maximized
discard runCommand("/usr/bin/xfconf-query",
args=["--channel=xfwm4", "--property=/general/borderless_maximize", "--create", "--type=bool", "--set=true"])
# Hide top bar of windows when maximized
discard runCommand("/usr/bin/xfconf-query",
args=["--channel=xfwm4", "--property=/general/titleless_maximize", "--create", "--type=bool", "--set=true"])
# Put window buttons on left side
discard runCommand("/usr/bin/xfconf-query",
args=["--channel=xfwm4", "--property=/general/button_layout", "--create", "--type=string", "--set=CMH|"])
return true
proc disableTopBarIntegration(): bool =
if isGlobalMenuEnabled():
# Disable global menu
let exitCode = runCommand("/usr/bin/pkexec", ["/usr/bin/toggle-global-menu", "disable"])
case exitCode
of 0:
discard
of 126:
return false
of 127:
sendNotification(appID, "Layout Switcher", "Authentication failed!")
else:
sendNotification(appID, "Failed removing global menu!", "Make sure that you are not currently installing any apps or updating the system.")
return false
# Hide window borders when maximized
discard runCommand("/usr/bin/xfconf-query",
args=["--channel=xfwm4", "--property=/general/borderless_maximize", "--create", "--type=bool", "--set=true"])
# Don't hide top bar of windows when maximized
discard runCommand("/usr/bin/xfconf-query",
args=["--channel=xfwm4", "--property=/general/titleless_maximize", "--create", "--type=bool", "--set=false"])
# Put window buttons on right side
discard runCommand("/usr/bin/xfconf-query",
args=["--channel=xfwm4", "--property=/general/button_layout", "--create", "--type=string", "--set=|HMC"])
return true
proc enableLayout(layoutName: string) =
case layoutName
of "Windows-Like", "MX-Like", "Gnome-Like", "TopX-Like":
if not disableTopBarIntegration():
return
of "Unity-Like", "MacOS-Like":
if not enableTopBarIntegration():
return
else:
return
discard runCommand("/usr/bin/xfce4-panel-profiles", ["load", profilesDir / layoutName & ".tar.bz2"])
if runCommand("/usr/bin/killall", ["mate-hud"]) == 0:
discard runCommand("/usr/bin/setsid", ["-f", "/usr/lib/mate-hud/mate-hud"])
sleep(5000)
sendNotification(appID, "Layout Switcher", layoutName & " layout was enabled",
icon = iconsDir / layoutName.toLowerAscii() & "-layout.png")
var
oldConfigDir: Option[string]
configDirChanged: bool
# Prevent loading GTK theme from ~/.config/gtk-4.0 directory when it is a symlink
if symlinkExists(getConfigDir() / "gtk-4.0"):
if existsEnv("XDG_CONFIG_HOME"):
oldConfigDir = some(getEnv("XDG_CONFIG_HOME"))
putEnv("XDG_CONFIG_HOME", "/dev/null")
configDirChanged = true
viewable App:
hooks:
build:
# Reset the user's XDG_CONFIG_HOME variable back to what it was before
if configDirChanged == true:
if oldConfigDir.isNone():
delEnv("XDG_CONFIG_HOME")
else:
putEnv("XDG_CONFIG_HOME", get(oldConfigDir))
method view(app: AppState): Widget =
result = gui:
Window:
title = "TROMjaro Layout Switcher"
# Shrink window to the smallest size
defaultSize = (0, 0)
iconName = "tromjaro-layout-switcher"
Box(orient = OrientY, margin = 7, spacing = 5):
Box(orient = OrientX):
Label {.hAlign: AlignEnd.}:
text = "Please use the"
LinkButton {.expand: false.}:
text = "Panel Profiles"
proc clicked() =
discard runCommand("/usr/bin/setsid", ["-f", "/usr/bin/xfce4-panel-profiles"])
Label {.hAlign: AlignStart.}:
text = "to save your current configuration in case you did any manual changes, else you may lose them."
Label:
text = "Changing to or from any layout that has global menu will require your admin password."
for row in layoutsGrid:
Box(orient = OrientX, spacing = 5):
for tooltip in row:
let layoutName = tooltip.split(' ', 1)[0]
Button {.vAlign: AlignCenter, hAlign: AlignCenter.}:
icon = layoutName.toLowerAscii() & "-layout"
tooltip = tooltip
style = [ButtonFlat, StyleClass("layout-button")]
proc clicked() =
enableLayout(layoutName)
brew(appID, gui(App()), icons=[iconsDir], stylesheets=[newStylesheet(gtkCSS)])