Open blueray453 opened 2 years ago
I haven't tested this yet, but it's likely this is a bug in xdotool.
Here's the bug I think is going on, and it can be tested later:
--sync
flag will make the windowsize
command wait until the window size changesQuestion: After snapping/tiling, then running the command, does the window's size change at all when xdotool windowsize is run?
It does not change until i drag of move the window. If i move the window from tiled or snapped position, then it give output.
For example, I have a script like:
#!/bin/bash
WINDOW_ID=$(xdotool getactivewindow)
CLASS_NAME=$(xprop -id $WINDOW_ID | rg WM_CLASS | cut -d '"' -f2)
WORKSPACE=$(xdotool get_desktop)
WindowsArray=()
for i in $(xdotool search --onlyvisible --desktop $WORKSPACE --classname $CLASS_NAME); do
WindowsArray+=($i)
done
SCREEN_WIDTH=3440
SCREEN_HEIGHT=1331
# 1 is 4 windows, 2 is 8 windows
FOUR_OR_EIGHT=1
allX=(0 $(( $SCREEN_WIDTH / 4 )) $(( $SCREEN_WIDTH / 2 )) $(( $SCREEN_WIDTH / 4 * 3 )) 0 $(( $SCREEN_WIDTH / 4 )) $(( $SCREEN_WIDTH / 2 )) $(( $SCREEN_WIDTH / 4 * 3 )))
allY=(0 0 0 0 665 665 665 665)
WINDOW_WIDTH=$(( $SCREEN_WIDTH / 4 ))
WINDOW_HEIGHT=$(( $SCREEN_HEIGHT / $FOUR_OR_EIGHT ))
ITER=0
for win in ${WindowsArray[@]}; do
xdotool windowsize "${win}" $WINDOW_WIDTH $WINDOW_HEIGHT
xdotool windowmove "${win}" ${allX[$ITER]} ${allY[$ITER]}
xdotool windowactivate "${win}"
((ITER++))
if [[ $ITER == $(( 4 * $FOUR_OR_EIGHT )) ]]
then
break
fi
done
If I bind it to a key, it will not work on the windows that are tiled or snapped (even though their id is in WindowsArray
).
This helps, thank you!
I'm thinking that xdotool could detect when a window has been docked/tiled by the window manager and maybe it could remove that state (docked, etc) when a windowmove/windowsize command is given.
I haven't tried this yet, though.
I ran xprop
and xwininfo
on both tiled (window with issues) and untiled (window without issues) window.
In a tiled window,
_NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_FOCUSED
In a untiled window,
_NET_WM_STATE(ATOM) = _NET_WM_STATE_FOCUSED
I think the problem is with _NET_WM_STATE_MAXIMIZED_VERT
If I can get a command to set and unset atoms namely _NET_WM_STATE_MAXIMIZED_VERT
, and _NET_WM_STATE_MAXIMIZED_HORZ
then I hopefully will be able to confirm.
I have tiled a window then remove _NET_WM_STATE_MAXIMIZED_VERT
using:
xprop -id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) -f _NET_WM_STATE 32a -set _NET_WM_STATE ""
still it does not work.
The news is, i replace the xdotool
commands with wmctrl
and the bug is still there.
#!/bin/bash
# getactivewindow
# selectwindow
WINDOW_ID=$(xdotool getactivewindow)
# WINDOW_ID=$(wmctrl -a :ACTIVE: -v 2>&1 | grep -Eo "0x[0-9a-f]{8}")
CLASS_NAME=$(xprop -id $WINDOW_ID | rg WM_CLASS | cut -d '"' -f2)
WORKSPACE=$(xdotool get_desktop)
xdotool search --onlyvisible --desktop $WORKSPACE --classname $CLASS_NAME | sort -n > /tmp/align-four-windows
NUMBER_OF_WINDOWS=$(cat /tmp/align-four-windows | wc -l)
SCREEN_WIDTH=3440
SCREEN_HEIGHT=1331
WINDOWS_PER_CONTAINER=4
WINDOW_HEIGHT=$(( $SCREEN_HEIGHT ))
WINDOW_WIDTH=$(($SCREEN_WIDTH/$WINDOWS_PER_CONTAINER))
# make 4 slice of 0-100
# 0, 25, 50, 75
# number_to_divide=100
# slice_of_number=4
# number_divide_by=$(($number_to_divide/$slice_of_number))
# slices=()
# for ((n=0;n<$slice_of_number;n++)); do
# slices[$n]+=$(($number_divide_by*$n))
# done
# for value in "${slices[@]}"
# do
# echo $value
# done
allX=()
for ((n=0;n<$WINDOWS_PER_CONTAINER;n++)); do
allX[$n]+=$(($WINDOW_WIDTH*$n))
done
function_name () {
ITER=0
# HOW=$(echo "sed -n ${1}p /tmp/align-four-windows" >> /home/ismail/Desktop/test/debug.txt)
# HOW=$(echo "sed ${1}d /tmp/align-four-windows" >> /home/ismail/Desktop/test/debug.txt)
for win in $(sed "${1}"d /tmp/align-four-windows); do
xdotool windowminimize "${win}"
# wmctrl -i -r $win -b toggle,shaded
done
for win in $(sed -n "${1}"p /tmp/align-four-windows); do
# xdotool windowactivate "${win}"
# wmctrl -i -r $win -e 0,${allX[$ITER]},0,$WINDOW_WIDTH,$WINDOW_HEIGHT
xdotool windowsize "${win}" $WINDOW_WIDTH $WINDOW_HEIGHT
xdotool windowmove "${win}" ${allX[$ITER]} 0
xdotool windowactivate "${win}"
((ITER++))
done
}
# round a float to the nearest integer above its current value
((NUMBER_OF_STATES=($NUMBER_OF_WINDOWS+$WINDOWS_PER_CONTAINER-1)/$WINDOWS_PER_CONTAINER))
# Three States
state="/tmp/align-four-windows-state"
index=$(cat "$state" 2>/dev/null)
[[ -z "$index" ]] && index=0 || index=$((++index % $NUMBER_OF_STATES))
printf "%d\n" $index >"$state"
# 1,4
# 5,8
# 9,12
# 13,16
# value_to_add=4
# loop_n_times=5
# for ((n=1;n<=loop_n_times;n++)); do
# DIVX=$((value_to_add - 1))
# BOX=$(($value_to_add * $n))
# echo $(($BOX - $DIVX )) $BOX
# done
NUMBER_TO_SUBTRACT=$((WINDOWS_PER_CONTAINER - 1))
TO_WINDOW=$((WINDOWS_PER_CONTAINER * (index + 1) ))
function_name "$((TO_WINDOW - NUMBER_TO_SUBTRACT )),$TO_WINDOW"
In the given code:
If I replace:
xdotool windowsize "${win}" $WINDOW_WIDTH $WINDOW_HEIGHT
xdotool windowmove "${win}" ${allX[$ITER]} 0
xdotool windowactivate "${win}"
with
xdotool windowactivate "${win}"
wmctrl -i -r $win -e 0,${allX[$ITER]},0,$WINDOW_WIDTH,$WINDOW_HEIGHT
you will still find the bug for snapped or tiled windows.
Few things about the script. You have to bind this key to a keyboard shortcut. This script shows four window of current app in current workspace. If there are more than four windows then it toggles. The SCREEN_WIDTH
and SCREEN_HEIGHT
is hardcoded (because of the original bug i reported). You can choose how many windows you want to see at a time using WINDOWS_PER_CONTAINER
.
I have done some research.
https://discourse.gnome.org/t/what-are-the-commands-for-the-given-keybindings/10868
It will be hard to maintain compatibility with gnome.
The best solution might be to crate a gnome extension that will give us some commands. Which we will invoke using busctl, dbus-send or gdbus etc.
For example, if we install https://github.com/hseliger/window-calls-extended
we can now run:
% gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/WindowsExt --method org.gnome.Shell.Extensions.WindowsExt.List | cut -c 3- | rev | cut -c4- | rev | jq .
[
{
"class": "Fsearch",
"pid": 20893,
"id": 1140312234,
"maximized": 0,
"focus": false,
"title": "FSearch"
},
{
"class": "VSCodium",
"pid": 2156,
"id": 1140312235,
"maximized": 0,
"focus": false,
"title": "● init.adoc - gnome-extension - VSCodium"
},
{
"class": "Nemo",
"pid": 14514,
"id": 1140312243,
"maximized": 0,
"focus": false,
"title": "dbus - /media/ismail/SSDWorking/_Working/_NotesFiltered/linux/dbus"
},
{
"class": "Nemo-desktop",
"pid": 1937,
"id": 1140312236,
"maximized": 0,
"focus": false,
"title": "Desktop"
},
{
"class": "firefox",
"pid": 17717,
"id": 1140312237,
"maximized": 2,
"focus": false,
"title": "ickyicky/window-calls: Gnome Extension for getting windows list in wayland — Mozilla Firefox"
},
{
"class": "Nemo",
"pid": 14514,
"id": 1140312242,
"maximized": 2,
"focus": false,
"title": "extensions - /home/ismail/.local/share/gnome-shell/extensions"
},
{
"class": "firefox",
"pid": 17717,
"id": 1140312238,
"maximized": 0,
"focus": false,
"title": "xdotool hang if I tile / snap the window · Issue #398 · jordansissel/xdotool — Mozilla Firefox"
},
{
"class": "Alacritty",
"pid": 24890,
"id": 1140312247,
"maximized": 2,
"focus": true,
"title": "Alacritty"
},
{
"class": "Nemo",
"pid": 14514,
"id": 1140312239,
"maximized": 0,
"focus": false,
"title": "nemo"
},
{
"class": "Nemo",
"pid": 14514,
"id": 1140312240,
"maximized": 0,
"focus": false,
"title": "nemo"
},
{
"class": "firefox",
"pid": 17717,
"id": 1140312241,
"maximized": 0,
"focus": false,
"title": "Firefox"
},
{
"class": "Gnome-shell",
"pid": 24048,
"id": 1140312244,
"maximized": 0,
"focus": false,
"title": "gnome-shell"
}
]
For example, there is an extension https://github.com/gonzaarcr/unmaximize-gnome-ext which unmaximize window on panel double click. We might modify it to unmaximize a window by it's id. Or, unmaximize multiple windows by class (it will have to have a dbus interface, so that we can run it via shell script).
Same way, getactivewindow, get_desktop, windowminimize, windowsize, windowmove, windowactivate etc. will have to have dbus commands.
The point is, xdotool will now need a gnome extension. And behind the scene it will call dbus commands.
That way we will get unmaximize type features which i think xdotool currently do not have. We will also get wayland compatibility.
I am not an expert. I might be wrong in so many level. Please let me know in case there is a better solution.
This is the library we are looking at to manage windows
https://gjs-docs.gnome.org/meta9~9_api/meta.window#method-activate
You might find the following gists interesting
https://gist.github.com/rbreaves/257c3edfa301786e66e964d7ac036269 https://gist.github.com/tuberry/dc651e69d9b7044359d25f1493ee0b39
It does not seem to be a xdotool
issue. I have filed a bug report on https://gitlab.gnome.org/GNOME/mutter/-/issues/2407
Hmm. I have an idea.
I have tiled a window then remove _NET_WM_STATE_MAXIMIZED_VERT using
xprop -id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) -f _NET_WM_STATE 32a -set _NET_WM_STATE ""
still it does not work.
I don't think this is the correct way to change this property. Here's what I found:
These properties are used as part of EWMH, a standard for window managers, applications, and accessory tools like window pagers to work together.
In order to communicate a change to _NET_WM_STATE, EWMH says this:
To change the state of a mapped window, a Client MUST send a _NET_WM_STATE client message to the root window
In your example, you are using xprop -set
. Reading the xprop source code, it looks like -set
calls XChangeProperty
: https://gitlab.freedesktop.org/xorg/app/xprop/-/blob/master/xprop.c#L1807-1808
xdotool has a command for changing properties using EWMH's protocol, windowstate
, code here: https://github.com/jordansissel/xdotool/blob/master/xdo.c#L1948-L1967
Try this, to remove the "maximized vertically" state on the currently-active window, try:
xdotool getactivewindow windowstate --remove MAXIMIZED_VERT
This could remove the tiled attribute from the window and then allow your window sizing commands to work. Let me know if this helps? xprop -id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) -f _NET_WM_STATE 32a -set _NET_WM_STATE ""
If I run the following commands one after another then it works.
xdotool getactivewindow windowstate --remove MAXIMIZED_VERT
xdotool getactivewindow windowsize --sync 100% 100% getwindowgeometry --shell
Nice! I'm glad we got it figured out :)
in the future, we could probably add a --sync
flag to the windowstate
command to have it wait until the state is removed from the window; that would help with any timing issues like windowsize running before the window manager has removed the maximized_vert state.
Have you checked https://gitlab.gnome.org/GNOME/mutter/-/issues/2407 ?
They said:
"Tiled" is treated as a window state like "maximized", so the window is positioned and sized automatically until it becomes unconstrained again.
I am not sure by what they meant by unconstrained , but i checked https://gjs-docs.gnome.org/clutter9~9_api/clutter.actor#property-constraints and there are
I also checked https://gjs-docs.gnome.org/meta9~9_api/meta.window#method-get_tile_match
get_tile_match()
most interesting to me was:
https://gjs-docs.gnome.org/meta9~9_api-keybindingaction/ and, https://gjs-docs.gnome.org/meta9~9_api/meta.keybindingaction#default-toggle_tiled_left
TOGGLE_TILED_LEFT = 39 TOGGLE_TILED_RIGHT = 40 TOGGLE_ABOVE = 41
I am not proficient at this. otherwise i would have tried to figure this out myself. Please let us know why clicking maximize button on a tiled window maximizes it, but running xdotool getactivewindow windowsize 100% 100%
on a tiled window does not maximize it. What is the native and optimal solution here?
there are also
https://gjs-docs.gnome.org/clutter9~9_api/clutter.actor#method-clear_constraints
get_constraints() clear_constraints()
I did not notice it earlier.
"Tiled" is treated as a window state like "maximized"
Actually xdotool getactivewindow windowsize 40% 40%
also does not work on a maximized window.
xdotool version 3.20160805.1
I have tested on Zorin OS 16 (gnome) and Linux Mint 21
If I tile / snap the terminal emulator to the left, then the following command hangs (just like when we run
cat
).