2023-12-26 19:02:06 +00:00
from std / os import symlinkExists , getConfigDir , ` / `
2023-12-25 07:50:13 +00:00
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 : 200 px;
min - width : 300 px;
} """
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. \n Enabling 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
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 :
2023-12-25 15:23:03 +00:00
loading : bool
2023-12-25 07:50:13 +00:00
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 ) )
2023-12-25 15:23:03 +00:00
proc enableLayout ( args : tuple [ layoutName : string , app : AppState ] ) {. thread . } =
let
layoutName = args . layoutName
app = args . app
defer :
app . loading = false
app . redrawFromThread ( )
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
# Load the layout profile
discard runCommand ( " /usr/bin/xfce4-panel-profiles " , [ " load " , profilesDir / layoutName & " .tar.bz2 " ] )
# Restart mate-hud
if runCommand ( " /usr/bin/killall " , [ " mate-hud " ] ) = = 0 :
discard runCommand ( " /usr/bin/setsid " , [ " -f " , " /usr/lib/mate-hud/mate-hud " ] )
sendNotification ( appID , " Layout Switcher " , layoutName & " layout was enabled " ,
icon = iconsDir / layoutName . toLowerAscii ( ) & " -layout.png " )
var thread : Thread [ ( string , AppState ) ]
2023-12-25 07:50:13 +00:00
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 "
2023-12-25 15:23:03 +00:00
if app . loading :
Box ( orient = OrientY , margin = 70 ) :
Spinner ( spinning = true )
Label ( text = " Loading your layout, please wait... " ) {. expand : false . }
else :
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 ( ) =
app . loading = true
createThread ( thread , enableLayout , ( layoutName , app ) )
2023-12-25 07:50:13 +00:00
brew ( appID , gui ( App ( ) ) , icons = [ iconsDir ] , stylesheets = [ newStylesheet ( gtkCSS ) ] )
2023-12-25 15:23:03 +00:00
2023-12-26 18:48:04 +00:00
if running ( thread ) :
joinThread ( thread )