I want to change position of a window. My problem is that the window can be maximized, this does not allow to change its size and location (window can belong to any application). I use KDE4.
I tried to use ewmh Python module. In my case when the window is maximized I just want to move it from one monitor to the other, keeping it maximized. I need to unmaximize it to set its geometry, so I tried to unmaximize it using ewmh.setWmState()
to set _NET_WM_STATE_MAXIMIZED_VERT
, _NET_WM_STATE_MAXIMIZED_HORZ
to 0
, then ewmh.display.flush()
.
Sometimes I can configure the position and size of a previously maximized window, sometimes not. For some reason it does not work reliably, and is especially likely to fail for maximized windows if I just switched from a single-monitor to triple monitors with xrandr
.
Please note that unmaximizing always works, what (often) does not work is changing window position (or size) afterwards.
I also tried doing this in the terminal. This is the easiest way to reproduce my problem. First, get the Window ID ($WID
) for some maximized window. Then:
wmctrl -i -r $WID -b remove,maximized_vert,maximized_horz
wmctrl -i -r $WID -e 0,1280,50,1250,1250
But the second command does nothing unless I move or resize the window manually before running it. Unlike ewmh
, wmctrl
never works as expected if the window is maximized. wmctrl
unmaximizes the window successfully but cannot change its position or size afterwards.
This is reproducible in both the single and triple monitor X screen states.
This problem seems to be not specific to any particular tool. For example, xdotool also fails to change window size/location if the window was just unmaximized but was not moved/resized manually.
The only reliable workaround I have found so far is to unmaximize the window, either manually, with ewmh
or with wmctrl
, and then manually change the window size or manually move it a bit. Only then I always can move or resize it with ewmh
or wmctrl
. But obviously this is not acceptable solution.
Is there reliable way to set window geometry even if the window is currently maximized? A method through Python is preferred, but a solution with shell commands will be fine too.
Press Alt + F7 to move a window or Alt + F8 to resize. Use the arrow keys to move or resize, then press Enter to finish, or press Esc to return to the original position and size.
Resize a Window Using Keyboard in Windows After that press Alt + Space shortcut keys together on the keyboard to open the window menu. Now, press S. The mouse cursor will turn into a cross with arrows. Then use the left, right, up, and down arrow keys to resize your window.
Use the arrow keys to resize the window. Press-and-hold Alt, then middle-click near the corner that you want to resize. The mouse pointer changes to indicate that you can resize from the corner. To resize the window, drag from the corner on which you middle-clicked.
Thanks to n.m. comment I found a solution. Here are relevant parts from my python script (it saves and restores state and geometry of all windows, so this example unmaximizes, unmaps and maps all windows):
from time import sleep
from ewmh import EWMH
from Xlib import display, protocol, X
from Xlib.protocol.request import *
...
ewmh = EWMH()
disp = display.Display()
poll_interval = 0.025 # s
poll_attempts_limit = 10
...
def unmaximize(window):
ewmh.setWmState(window, 0, "_NET_WM_STATE_MAXIMIZED_VERT")
ewmh.setWmState(window, 0, "_NET_WM_STATE_MAXIMIZED_HORZ")
...
for client in all_win:
unmaximize(client.window)
ewmh.display.flush()
for client in all_win:
client.xwin.unmap()
poll_attempts = 0
for client in all_win:
while client.xwin.get_attributes().map_state == X.IsViewable \
and poll_attempts < poll_attempts_limit:
sleep(poll_interval)
poll_attempts += 1
for client in all_win:
client.xwin.map()
poll_attempts = 0
for client in all_win:
while client.xwin.get_attributes().map_state != X.IsViewable \
and poll_attempts < poll_attempts_limit:
sleep(poll_interval)
poll_attempts += 1
After executing this code it is possible to set window geometry for any window. all_win
is a list of all windows represented as list of custom class objects populated with data from ewmh.getClientList()
. Each client.xwin = disp.create_resource_object("window", client.id)
. Waiting for mapping/unmapping to finish is important, otherwise it will be unreliable. Also, it is necessary to limit poll attempts to prevent infinite loop in case some window gets mapped or unmapped unexpectedly.
If you do not want to reconfigure a lot of windows at once, there is no noticeable performance improvement from using python xlib module for unmapping and mapping, it is easier to use xdotool instead:
from os import system
...
system("xdotool windowunmap --sync " + str(client.window.id))
system("xdotool windowmap --sync " + str(client.window.id))
If you want to set window geometry in shell script the following example should work even if the window is maximized:
wmctrl -i -r $WID -b remove,maximized_vert,maximized_horz
xdotool windowunmap --sync $WID
xdotool windowmap --sync $WID
wmctrl -i -r $WID -e 0,$x,$y,$width,$height
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With