Script: Vensters uitlijnen

Alles over programmeren in Linux
Gebruikersavatar
Mogenblue
Held
Held
Berichten: 351
Lid geworden op: Wo 18 Okt 2017, 08:27
Locatie: Amsterdam

Script: Vensters uitlijnen

Berichtdoor Mogenblue » Di 30 Aug 2022, 16:52

Er zijn extensies beschikbaar voor Cinnamon om de vensters op je werkblad uit te lijnen, maar ik vind ze niet even prettig werken.
Ik heb er zelf maar eentje gemaakt.

Dit script lijnt de vensters van het huidige werkblad uit. Je kunt ze ook sorteren door ze op de gewenste volgorde vanaf de linkerkant te zetten.
Uitlijning gebeurt vanaf de linkerbovenkant naar rechts en dan over daaronder volgende rijen ook van links naar rechts. Op die manier kun je zelf de volgorde op het werkblad bepalen.

Het is de bedoeling om het script vanuit het menu te starten omdat je dan geen extra vensters nodig hebt om het script uit te voeren. Je zou het eventueel ook in het contextmenu van Nemo kunnen plaatsen.

Er is een uitgebreide rapportage naar het scherm van wat het script doet, maar daarvoor moet je het dan wel in een venster openen. Wat je dan kan doen is eerst de vensters die je wil uitlijnen op het eerste werkblad openen en dan op een ander werkblad je bestandbeheerder openen en van daaruit het script starten. Dan kun je het in een terminal laten uitvoeren en dan krijg je alle uitvoer in de terminal te zien.
Dat werkt niet zonder meer want het script lijnt de vensters van het huidige werkblad uit.
Op regel 39 van het script kun je daarom mbv
#ActiveWorkSpaceID=0
het werkblad forceren dat moet worden uitgelijnd. Haal het hekje weg en selecteer het werkblad waarop de vensters staan die wil laten uitlijnen. Het eerste werkblad begint met 0.

Er zijn twee versies beschikbaar. De eerste is direct te gebruiken, maar je moet het natuurlijk wel uitvoerbaar maken.
De tweede versie moet je ietsje bijwerken. In die versie heb ik de spaties van inspringingen vervangen door sterretjes (*). Je moet daarom eerst de sterretjes door spaties vervangen. Inspringen gebeurt in mijn tekstbewerker met 4 spaties tegelijk. In je tekstbewerker moet je dan 4 sterretjes tegelijk door 4 spaties tegelijk vervangen. Als je dat in het bestand op je computer doet blijft de inspringing netjes behouden. Dat verbetert de leesbaarheid.


Bij het vullen van de sorteerlijst wordt de linkerpositie verhoogd met een constante. Dat is nodig om de waarde van alle vensters uit 4 cijfers te laten bestaan en om te zorgen dat er geen negatieve waarden in de array komen. Dat kan als je een venster links buiten het scherm schuift. Daar kan het sorteer proces niet goed mee overweg. Door die constante is de linkerpositie altijd groter dan 1000. Als een waarde 3 cijfers heeft staat het schermadres niet op de goede plek en kan dat niet goed worden uitgelezen. Of dan moet dat op een andere manier gebeuren.
Na het sorteren wordt die constante weer van de waarde afgetrokken zodat je dan weer de oude waarde hebt. Dat is niet persé nodig omdat de positie bij het uitlijnen toch wordt veranderd. De enige waarde die na het sorteren nog van belang is is de hexadecimale schermID. Maar het is wat makkelijker om het proces te volgen.

Het sorteren op zich is vrij gemakkelijk. Daar heb ik op internet een mooie snippet voor gevonden. Omstreeks regel 135:
IFS=$'\n' TargetList=($(sort <<<"${SortList[*]}")); unset IFS

Ik heb nog een tweede methode eronder staan, maar de eerste werkt goed genoeg.

Met de gesorteerde lijst wordt dan de HexWinIDList gevuld. Hier staan de adressen in van de vensters gesorteerd op linkerpositie.


Hier volgt de code van het direct te gebruiken script. Het heet vensters-uitlijnen.sh.

Code: Selecteer alles

#!/bin/bash


# Array voor minimum aantal vensters voor aantal banen vanaf 1. Aantal banen is het volgnummer in de array.
# Minimum aantal vensters is de waarde in de array.
# Dus 1 baan voor minimaal 1 venster, 2 banen voor minimaal 3 vensters, 3 banen voor minimaal 7 vensters, etcetera.
declare -a MinAantalVenstersTotaalBanen=(1 3 7 16 25)

# correctie voor breedte en hoogte van de rand van elk venster, kan per scherm/thema verschillen
VensterRandBreedte=10
VensterRandHoogte=5

# wachttijd tussen positioneren van vensters
Vertraging=0

# sorteren gebeurt tov de linkerafstand vh scherm
# sorteerconstante, bij 4k schermen moet de waarde minimaal boven de 1000 liggen
# zodat de Left-waarden hetzelde aantal cijfers hebben in de te sorteren array en altijd positief zijn
SorteerConstante=5000

#-------------------------------------------------------------------------------------------------------------

# The nullglob option causes an array to be empty if there are no matches.
shopt -s nullglob

#-------------------------------------------------------------------------------------------------------------


echo .
echo .
echo .


echo .
echo "Werkbladen:"
wmctrl -d
ActiveWorkSpaceID=$(wmctrl -d | awk '/\*/')
ActiveWorkSpaceID=${ActiveWorkSpaceID:0:1}
#ActiveWorkSpaceID=0
echo "Huidige werkblad ID is -$ActiveWorkSpaceID-"
echo .
echo .


# plaats vensterlijst in array
mapfile -t WindowSourceList < <( wmctrl -lpG )

echo "WindowSourcelist:"
printf "%s\n" "${WindowSourceList[@]}"


# eerste element is het bureaublad; lees de schermafmetingen en verwijder het element
Item="${WindowSourceList[0]}"
SchermBreedte=${Item:31:4}
SchermHoogte=${Item:36:4}
# maak element leeg om te verwijderen
WindowSourceList[0]=""

echo .
echo .
echo "Schermhoogte: ${SchermHoogte}"
echo "Schermbreedte: ${SchermBreedte}"

# randbreedte en hoogte aanpassen bij 4k schermen
if [ $SchermBreedte -gt 2000 ]
then
echo "4k scherm gedetecteerd. Vensterranden verdubbelen."
let VensterRandBreedte=VensterRandBreedte+VensterRandBreedte
let VensterRandHoogte=VensterRandHoogte+VensterRandHoogte
fi


echo .
echo .
echo "Vensterlijst corrigeren"
# Kopieer array naar nieuwe array en verwijder lege elementen en elementen van andere werkbladen
a=0
for Item in "${WindowSourceList[@]}"; do

if [ -z "$Item" ]
then
# item is leeg, ga direct naar volgende element
continue
fi

if ! [ $ActiveWorkSpaceID -eq "${Item:12:1}" ]
then
# item is niet op huidige werkblad, ga direct naar volgende element
echo "WerkbladID: -${Item:12:1}- skip"
continue
fi

echo "WerkbladID: -${Item:12:1}- toevoegen"

# voeg element toe aan de nieuwe arrays
WindowList[a]=$Item

HexWinID=${Item:0:10}
Left=${Item:21:4}

let Left=Left+SorteerConstante

SortList[a]="$Left $HexWinID"

(( a++ ))
done


AantalVensters=${#WindowList[@]}
echo .
echo .
echo "$AantalVensters vensters in de nieuwe array."

#controleer miminum aantal vensters voor uitlijnen
if [ $AantalVensters -lt 2 ]
then
echo "Te weinig vensters om uit te lijnen."
exit
fi


echo .
echo .
echo "Aangepaste vensterlijst voor huidige werkblad: "
printf "%s\n" "${WindowList[@]}"


echo .
echo .
echo "SortList: "
printf "%s\n" "${SortList[@]}"


# sorteer array, eerste methode is compacter
IFS=$'\n' TargetList=($(sort <<<"${SortList[*]}")); unset IFS
#readarray -t TargetList < <(for a in "${SortList[@]}"; do echo "$a"; done | sort)


a=0
for Item in "${TargetList[@]}"; do

HexWinID=${Item:5:10}
Left=${Item:0:4}

let Left=Left-SorteerConstante

Item="$Left $HexWinID"
TargetList[a]=$Item
HexWinIDList[a]=$HexWinID

(( a++ ))
done


echo .
echo .
echo "TargetList:"
printf "%s\n" "${TargetList[@]}"

echo .
echo .
echo "HexWinIDList na sortering:"
printf "%s\n" "${HexWinIDList[@]}"



# Set aantal banen en vensters per baan
AantalBanen=0
for MinVensters in "${MinAantalVenstersTotaalBanen[@]}"
do
if [ $AantalVensters -gt $MinVensters ]
then
(( AantalBanen++ ))
fi
done


VenstersPerBaan=$(echo "scale=1; ${AantalVensters} / ${AantalBanen} + 0.5" | bc)
# afronden op 0 decimalen
VenstersPerBaan=$(echo "scale=0; ${VenstersPerBaan} / 1" | bc)
#VenstersPerBaan=$(printf "%.0f" $(echo "scale=2; ${AantalVensters} / ${AantalBanen}" | bc))


echo .
echo .
echo "$AantalVensters vensters worden verdeeld over $AantalBanen banen."
echo "$VenstersPerBaan vensters per baan (afgerond op 0 decimalen)."


BaanHoogte=$(echo "scale=0; $SchermHoogte / $AantalBanen" | bc)
VensterBreedte=$(echo "scale=0; $SchermBreedte / $VenstersPerBaan" | bc)
VensterHoogte=$BaanHoogte
echo .
echo "Hoogte van de banen en vensters worden ${SchermHoogte} / ${AantalBanen} = $VensterHoogte"
echo "Breedte van de vensters wordt ${SchermBreedte} / ${VenstersPerBaan} = $VensterBreedte"

let VensterHoogte=VensterHoogte+VensterRandHoogte+VensterRandHoogte
let VensterBreedte=VensterBreedte+VensterRandBreedte+VensterRandBreedte
echo .
echo "Gecorrigeerde Hoogte van de vensters wordt $VensterHoogte"
echo "Gecorrigeerde Breedte van de vensters wordt $VensterBreedte"


echo .
echo .
echo .
echo "Vensters positioneren per baan"
BaanNummer=0
a=0
VensterTop=0
let VensterTop=0-VensterRandHoogte-1
while [ $AantalBanen -gt $BaanNummer ]
do

VensterLeft=0
let VensterLeft=0-VensterRandBreedte-3
for (( i=0; i<$VenstersPerBaan; i++ ))
do

# zet venster op de juiste plek
echo "BaanNummer: $BaanNummer, left: ${VensterLeft}, top: ${VensterTop}, breedte: ${VensterBreedte}, hoogte: ${VensterHoogte}"
echo " a: $a, ${WindowList[a]}"
echo .
wmctrl -i -r ${HexWinIDList[a]} -e 0,${VensterLeft},${VensterTop},${VensterBreedte},${VensterHoogte}
sleep $Vertraging

let VensterLeft=VensterLeft+VensterBreedte-VensterRandBreedte-3
(( a++ ))
done

let VensterTop=VensterTop+VensterHoogte-VensterRandHoogte-3
(( BaanNummer++ ))
done


# vensterlijst opnieuw in array plaatsen
mapfile -t WindowList < <( wmctrl -lpG )

echo .
echo "Nieuwe vensterlijst elementen:"
printf "%s\n" "${WindowList[@]}"

echo .
echo klaar.


Maak het bestand uitvoerbaar voor je het gaat gebruiken.
En maak een menu item aan onder je hoofdmenu. Bij mij staat ie onder Overig. In het menu item moet je hem dus niet in een terminal laten starten, want dan wordt dat meegesorteerd.
Gebruikersavatar
Mogenblue
Held
Held
Berichten: 351
Lid geworden op: Wo 18 Okt 2017, 08:27
Locatie: Amsterdam

Re: Script: Vensters uitlijnen

Berichtdoor Mogenblue » Di 30 Aug 2022, 16:54

Hier de versie met de sterretjes:

Code: Selecteer alles

#!/bin/bash


# Array voor minimum aantal vensters voor aantal banen vanaf 1. Aantal banen is het volgnummer in de array.
# Minimum aantal vensters is de waarde in de array.
# Dus 1 baan voor minimaal 1 venster, 2 banen voor minimaal 3 vensters, 3 banen voor minimaal 7 vensters, etcetera.
declare -a MinAantalVenstersTotaalBanen=(1 3 7 16 25)

# correctie voor breedte en hoogte van de rand van elk venster, kan per scherm/thema verschillen
VensterRandBreedte=10
VensterRandHoogte=10

# wachttijd tussen positioneren van vensters
Vertraging=0

# sorteren gebeurt tov de linkerafstand vh scherm
# sorteerconstante, bij 4k schermen moet de waarde minimaal boven de 1000 liggen
# zodat de Left-waarden hetzelde aantal cijfers hebben in de te sorteren array en altijd positief zijn
SorteerConstante=5000

#-------------------------------------------------------------------------------------------------------------

# The nullglob option causes an array to be empty if there are no matches.
shopt -s nullglob

#-------------------------------------------------------------------------------------------------------------


echo .
echo .
echo .


echo .
echo "Werkbladen:"
wmctrl -d
ActiveWorkSpaceID=$(wmctrl -d | awk '/\*/')
ActiveWorkSpaceID=${ActiveWorkSpaceID:0:1}
#ActiveWorkSpaceID=0
echo "Huidige werkblad ID is -$ActiveWorkSpaceID-"
echo .
echo .


# plaats vensterlijst in array
mapfile -t WindowSourceList < <( wmctrl -lpG )

echo "WindowSourcelist:"
printf "%s\n" "${WindowSourceList[@]}"


# eerste element is het bureaublad; lees de schermafmetingen en verwijder het element
Item="${WindowSourceList[0]}"
SchermBreedte=${Item:31:4}
SchermHoogte=${Item:36:4}
# maak element leeg om te verwijderen
WindowSourceList[0]=""

echo .
echo .
echo "Schermhoogte: ${SchermHoogte}"
echo "Schermbreedte: ${SchermBreedte}"

# randbreedte en hoogte aanpassen bij 4k schermen
if [ $SchermBreedte -gt 2000 ]
then
****echo "4k scherm gedetecteerd. Vensterranden verdubbelen."
****let VensterRandBreedte=VensterRandBreedte+VensterRandBreedte
****let VensterRandHoogte=VensterRandHoogte+VensterRandHoogte
fi


echo .
echo .
echo "Vensterlijst corrigeren"
# Kopieer array naar nieuwe array en verwijder lege elementen en elementen van andere werkbladen
a=0
for Item in "${WindowSourceList[@]}"; do

****if [ -z "$Item" ]
****then
********# item is leeg, ga direct naar volgende element
********continue
****fi

****if ! [ $ActiveWorkSpaceID -eq "${Item:12:1}" ]
****then
********# item is niet op huidige werkblad, ga direct naar volgende element
********echo "WerkbladID: -${Item:12:1}- skip"
********continue
****fi

****echo "WerkbladID: -${Item:12:1}- toevoegen"

****# voeg element toe aan de nieuwe arrays
****WindowList[a]=$Item

****HexWinID=${Item:0:10}
****Left=${Item:21:4}

****let Left=Left+SorteerConstante

****SortList[a]="$Left $HexWinID"

****(( a++ ))
done


AantalVensters=${#WindowList[@]}
echo .
echo .
echo "$AantalVensters vensters in de nieuwe array."

#controleer miminum aantal vensters voor uitlijnen
if [ $AantalVensters -lt 2 ]
then
****echo "Te weinig vensters om uit te lijnen."
****exit
fi


echo .
echo .
echo "Aangepaste vensterlijst voor huidige werkblad: "
printf "%s\n" "${WindowList[@]}"


echo .
echo .
echo "SortList: "
printf "%s\n" "${SortList[@]}"


# sorteer array, eerste methode is compacter
IFS=$'\n' TargetList=($(sort <<<"${SortList[*]}")); unset IFS
#readarray -t TargetList < <(for a in "${SortList[@]}"; do echo "$a"; done | sort)


a=0
for Item in "${TargetList[@]}"; do

****HexWinID=${Item:5:10}
****Left=${Item:0:4}

****let Left=Left-SorteerConstante

****Item="$Left $HexWinID"
****TargetList[a]=$Item
****HexWinIDList[a]=$HexWinID

****(( a++ ))
done


echo .
echo .
echo "TargetList:"
printf "%s\n" "${TargetList[@]}"

echo .
echo .
echo "HexWinIDList na sortering:"
printf "%s\n" "${HexWinIDList[@]}"



# Set aantal banen en vensters per baan
AantalBanen=0
for MinVensters in "${MinAantalVenstersTotaalBanen[@]}"
do
****if [ $AantalVensters -gt $MinVensters ]
****then
********(( AantalBanen++ ))
****fi
done


VenstersPerBaan=$(echo "scale=1; ${AantalVensters} / ${AantalBanen} + 0.5" | bc)
# afronden op 0 decimalen
VenstersPerBaan=$(echo "scale=0; ${VenstersPerBaan} / 1" | bc)
#VenstersPerBaan=$(printf "%.0f" $(echo "scale=2; ${AantalVensters} / ${AantalBanen}" | bc))


echo .
echo .
echo "$AantalVensters vensters worden verdeeld over $AantalBanen banen/baan."
echo "$VenstersPerBaan vensters per baan (afgerond op 0 decimalen)."


BaanHoogte=$(echo "scale=0; $SchermHoogte / $AantalBanen" | bc)
VensterBreedte=$(echo "scale=0; $SchermBreedte / $VenstersPerBaan" | bc)
VensterHoogte=$BaanHoogte
echo .
echo "Hoogte van de banen en vensters worden ${SchermHoogte} / ${AantalBanen} = $VensterHoogte"
echo "Breedte van de vensters wordt ${SchermBreedte} / ${VenstersPerBaan} = $VensterBreedte"

let VensterHoogte=VensterHoogte+VensterRandHoogte+VensterRandHoogte
let VensterBreedte=VensterBreedte+VensterRandBreedte+VensterRandBreedte
echo .
echo "Gecorrigeerde Hoogte van de vensters wordt $VensterHoogte"
echo "GecorrigeerdeBreedte van de vensters wordt $VensterBreedte"


echo .
echo .
echo .
echo "Vensters positioneren per baan"
BaanNummer=0
a=0
VensterTop=0
let VensterTop=0-VensterRandHoogte-1
while [ $AantalBanen -gt $BaanNummer ]
do

****VensterLeft=0
****let VensterLeft=0-VensterRandBreedte-3
****for (( i=0; i<$VenstersPerBaan; i++ ))
****do

********# zet venster op de juiste plek
********echo "BaanNummer: $BaanNummer, left: ${VensterLeft}, top: ${VensterTop}, breedte: ${VensterBreedte}, hoogte: ${VensterHoogte}"
********echo "************ a: $a, ${WindowList[a]}"
********echo .
********wmctrl -i -r ${HexWinIDList[a]} -e 0,${VensterLeft},${VensterTop},${VensterBreedte},${VensterHoogte}
********sleep $Vertraging

********let VensterLeft=VensterLeft+VensterBreedte-VensterRandBreedte-3
********(( a++ ))
****done

****let VensterTop=VensterTop+VensterHoogte-VensterRandHoogte-3
****(( BaanNummer++ ))
done


# vensterlijst opnieuw in array plaatsen
mapfile -t WindowList < <( wmctrl -lpG )

echo .
echo "Nieuwe vensterlijst elementen:"
printf "%s\n" "${WindowList[@]}"

echo .
echo klaar.



In je tekstbewerker moet je over het hele bestand elke 4 sterretjes door 4 spaties laten vervangen.

Terug naar “Programmeren”

Wie is er online

Gebruikers op dit forum: Geen geregistreerde gebruikers en 12 gasten