You are not logged in.
Hi guys,
I tried to create a couple of commands that open Thunderbird maximized on the left monitor on the default workspace. They worked however those look like a bit cumbersome and I wonder if I can improve the commands.
The panel launcher from the left monitor uses this command:
sh -c '/usr/bin/thunderbird & sleep 3 && wmctrl -r thunderbird -t 0 | wmctrl -r thunderbird -b add,maximized_vert,maximized_horz'
The panel launcher from the right monitor uses this other command:
sh -c '/usr/bin/thunderbird & sleep 3 && wmctrl -r thunderbird -b remove,maximized_vert,maximized_horz && wmctrl -r thunderbird -t 0 | wmctrl -r thunderbird -e "0,290,0,-1,-1" && sleep 1 && wmctrl -r thunderbird -b add,maximized_vert,maximized_horz'
Especially the latter looks like very amateur... What do you think?
Thanks,
D.
Last edited by Danielsan (2020-11-14 08:18:57)
Debian ~ Devuan & FreeBSD + XFCE = <3
Offline
Can you install Gdevilspie? It's a GUI for devilspie2 that (I heard) makes those operations easier to achieve.
Offline
The problem I have with devilspie it is because I don't want a daemon running in background just to open a bunch a of programs in certain way, many WMs have those features by default, XFCE should provide the same features as well...
Debian ~ Devuan & FreeBSD + XFCE = <3
Offline
Can you install Gdevilspie? It's a GUI for devilspie2 that (I heard) makes those operations easier to achieve.
No, that is a GUI for devilspie (without the 2) - I am the developer of devilspie2 (and neither 1 or 2 is under development any longer unfortunately). I don't know of any similar GUI tool for devilspie2.
Offline
I use the same approach with wmctrl with one difference: I made a script my_windows_move which moves windows. Script itself is:
#!/bin/bash
# Move working windows into its correct desktops
# Input file - SRC data
inpf=~/bin/$(basename $0).input
while IFS='' read -r line || [[ -n "$line" ]]; do
#echo "Text read from file: $line"
#desknum=$(echo $line| sed -r 's/^([0-9]+) .*$/\1/')
#echo "Desknum: $desknum"
# Pattern for correct input line
pat="^[0-9]+ .+"
if [[ $line =~ $pat ]]; then
desknum=$(echo $line| sed -r 's/^([0-9]+) .*$/\1/')
title=$(echo $line| sed -r 's/^[0-9]+ (.+)$/\1/')
echo "Desknum: $desknum, title: $title"
# Get title id from title substring
tid=$(wmctrl -l | grep "$title" | cut -d ' ' -f1)
for n in $tid ; do
echo "Found id: $n, moving..."
wmctrl -i -r $n -t $desknum
done
fi
done < "$inpf"
and this script reads data from a config file with the same name as the script + ".input" my_windows_move.input. The input file looks like this:
# Configuration file for my_windows_move
# Format:
# desktop_number window_substring
#
# window_substring - can have non backslashed spaces
#
# desktop_number in wmctrl:
# 0 | 1 | 2
# ---------
# 3 | 4 | 5
#
5 Thunderbird
3 SSL/SSH VNC Viewer
1 gFTP
I have another script which runs all applications I use most of days (the 3 above are just an example) and once all of them are running (some of them need me to type a password) I click on a shortcut and move windows into desired desktops.
For your purpose there would be necessary to add reading and using position coordinates of windows... Something like this I use only for Firefox and Vivaldi - I am bothered by the fact that XFCE can open many Thunar windows on proper desktops and positions, but it is not able to do the same with FireFox and Vivaldi (which is probably the applications fault). So I made another script, which I call before logout (I made a button which calls my personal logout script and then it makes shutdown/logout/reboot):
windows_positions --save
and the next day, after Firefox and Vivaldi are started:
windows_positions --restore
and the script windows_positions itself:
#!/bin/bash
# Move working windows into its correct places
usage="Usage: $(basename "$0") operation\n Operations:\
\n --save - saves windows position\
\n --restore - restores windows position"
operation=$1;[ -z "$operation" ] && echo -e "$usage" && exit 0
# Basic configuration
#
# Config file - same filename as current script name
cfgdir=~/.config/$(basename "$0")
cfg=$cfgdir/$(basename "$0").cfg
cfgt=$cfg.tmp
hostname=$(hostname)
# Array of applications to be saved (exact class, not only substring)
applications=("Navigator.Firefox" "vivaldi-stable.Vivaldi-stable")
# Diff between save and restore positions via wmctrl (what the hell???)
# (subtract diff before restoration)
diff_x=10
diff_y=44
#
# End of basic configuration
save_cfg () {
if [[ ! -d $cfgdir ]]; then
mkdir "$cfgdir"
fi
echo "Saving configuration to $cfg..."
{ echo -e "# This is windows position config file for script $(basename "$0")"
echo -e "# Saved positions for wmctrl command"
echo -e "# Generated by: $(basename "$0") --save\n"
echo -e "# Class must be defined first, followed by its titles until the next class.\n"
echo -e "# Format:"
echo -e "# minimized desktop_number position_x position_y width height win_title\n"
} > "$cfgt"
local p title a states minim i
for app in "${applications[@]}"; do
{ echo -e "\n# Application class: $app"
echo -e "class=$app"
} >> "$cfgt"
# Separator \n, separated lines into an array
IFS=$'\n' props=( $(wmctrl -lGx | grep "$app") )
# $p format (wmctrl -lGx): id desknum x y width height class hostname title
# $a format 0 1 2 3 4 5 6 7 8-x
# Pattern to remove anything except title
# Format: id gravity x y width height class hostname title
pat="^0x[0-9a-f]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +$app +$hostname +(.+)$"
for p in "${props[@]}"; do
title=$(sed -r "s/$pat/\1/" <<< "$p")
#echo "Title: $title"
# Convert line to array
IFS=' ' a=($p)
# echo "ID okna: ${a[0]}"
# Get state (minimized/non-minimized) of ${a[0]} window
states=( $(xprop -id "${a[0]}" | grep "window state") )
# echo "State: ${states[2]}"
# Window state Iconic = minimized
if [[ ${states[2]} == Iconic ]]; then
minim=1
else
minim=0
fi
#echo "State: ${states[2]}, minimized: $minim"
# Save minim desknum x y width height title
echo "$minim ${a[1]} ${a[2]} ${a[3]} ${a[4]} ${a[5]} $title" >> "$cfgt"
done
done
# Rotate 5+1 backup files
if [[ -f "$cfgt" ]]; then
for i in {5..1..-1}; do
if [[ -f "$cfg.$i" ]]; then
#echo "mv $cfg.$i $cfg.$(( i+1 ))"
mv "$cfg.$i" "$cfg.$(( i+1 ))"
fi
done
if [[ -f "$cfg" ]]; then
#echo "cp $cfg $cfg.1"
cp "$cfg" "$cfg.1"
fi
# Move tmp config file into current config file
#echo "mv $cfgt $cfg"
mv "$cfgt" "$cfg"
fi
echo "Configuration saved."
}
process_window () {
# Params: id desknum winvar
# Minimize a unminize must be first, the can move a window to current desktop
if [[ $minimized -eq 1 ]]; then
xwit -iconify -id "$1"
else
xwit -pop -id "$1"
fi
# Resize (-e) and move (-t) window must be done separately
# echo "wmctrl -i -r $n -e $3"
wmctrl -i -r "$1" -e "$3"
wmctrl -i -r "$1" -t "$2"
}
restore_cfg () {
echo "Restoring widows from $cfg..."
local cpat cpati lpat tpat cfgvar maxdesk line class appwindows
local patlx a minimized desknum pos_x pos_y winvar ctitle
local lwindow twindow tid
# Pattern for class defining line
cpat="^class="
cpati=${cpat}.+
# Pattern for correct input line
lpat="^[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ .+"
# Pattern what remove to get title from config file
tpat="^[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +(.+)$"
# Preprocess config file $cfg into $cfgvar
# Remove comments and empty lines
cfgvar=$(grep -v '^[[:space:]]*#' "$cfg" | grep -v -e '^[[:space:]]*$')
#echo -e "Cfgvar:\n$cfgvar"
# Maximal number of running desktops
maxdesk=$(wmctrl -d | tail -n 1 | cut -d ' ' -f1)
# Go through pre-processed config variable
while IFS='' read -r line || [[ -n "$line" ]]; do
# Only lines with defined pattern will be processed
if [[ $line =~ $cpati ]]; then
# Find new class and its running application windows
class=$(sed -r "s/$cpat//" <<< "$line")
echo -e "\nNew class: $class"
# Find running application windows (based on class)
appwindows=$(wmctrl -lx | grep -F "$class")
#echo -e "Appwindows: \n$appwindows\n"
# Pattern to remove anything except title from wmctrl -lx
# Format: id desknum class hostname title
patlx="^0x[0-9a-f]+ +[0-9]+ +$class +$hostname +(.+)$"
elif [[ $line =~ $lpat && ! -z $appwindows ]]; then
# Convert cfg line to array
IFS=' ' a=($line)
minimized=${a[0]}
desknum=${a[1]}
# Apply diff between save and restore via wmctrl
pos_x=$(( a[2]-diff_x ))
pos_y=$(( a[3]-diff_y ))
# winvar for wmctrl = gravity,x,y,width,height gravity=0
winvar="0,$pos_x,$pos_y,${a[4]},${a[5]}"
# Title from cfg
ctitle=$(sed -r "s/$tpat/\1/" <<< "$line")
echo -e "\nNew window from cfg:"
echo -e "Minimized: $minimized, desknum: $desknum, cfg title: $ctitle"
#echo "Win variables: $winvar"
if [[ $desknum -gt $maxdesk ]]; then
desknum=$maxdesk
echo "Desknum exceeded number of desktops, fixed to: $desknum"
fi
echo " "
# Go throuth all appwindows with the title (grep substing)
# Processed window is in lwindow (List window)
while read -r lwindow; do
# Real window title
rtitle=$(sed -r "s/$patlx/\1/" <<< "$lwindow")
echo -e "Going to exact compare of real title: $rtitle"
if [[ "$ctitle" == "$rtitle" ]]; then
# Exact title found, save it and stop searching
twindow=$lwindow
break
fi
done <<< "$(grep -F "$ctitle" <<< "$appwindows")"
# If a running window was found, process it.
if [[ ! -z $twindow ]]; then
echo "Running twindow found: $twindow"
tid=$(cut -d ' ' -f1 <<< "$twindow")
# Once twindow processed, empty variable
unset twindow
echo -e "Found id: $tid, moving..."
process_window $tid $desknum $winvar
# Remove processed line (identified by $tid) from $appwindows
appwindows=$(grep -v "^$tid" <<< "$appwindows")
#echo -e "\nCurrent appwindows:\n$appwindows\n"
else
echo "Exact title from cfg was not found among running windows."
fi
fi
done <<< "$cfgvar"
}
### Main run
if [[ "$operation" == --save ]]; then
save_cfg
exit 1
elif [[ "$operation" == --restore ]]; then
restore_cfg
exit 1
fi
exit 0
It is not perfect but it works well with pages which does not change title before --save and --restore.
These scripts are probably just for inspiration and probably not sufficient for your purpose.
Another approach could be a script which could read info from ~/.cache/sessions/xfwm4-*.state and restore windows according saved session info...
Offline
[ Generated in 0.009 seconds, 8 queries executed - Memory usage: 577.63 KiB (Peak: 594.6 KiB) ]