如何移动或调整 X11 窗口的大小(即使它们已最大化)?

Lis*_*yen 5 python linux x11 shell window

我想改变一个窗口的位置。我的问题是窗口可以最大化,这不允许更改其大小和位置(窗口可以属于任何应用程序)。我使用 KDE4。


我尝试使用ewmh Python 模块。在我的情况下,当窗口最大化时,我只想将它从一台显示器移动到另一台显示器,并保持最大化。我需要取消最大化它以设置其几何形状,因此我尝试使用ewmh.setWmState()to set _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZto 0, then取消最大化它ewmh.display.flush()

有时我可以配置以前最大化的窗口的位置和大小,有时不能。出于某种原因,它不能可靠地工作,如果我只是从单显示器切换到三显示器,则特别有可能无法最大化窗口xrandr.

请注意,取消最大化总是有效的,(通常)不起作用的是之后更改窗口位置(或大小)。


我也尝试在终端中执行此操作。这是重现我的问题的最简单方法。首先,获取$WID某个最大化窗口的窗口 ID ( )。然后:

wmctrl -i -r $WID -b remove,maximized_vert,maximized_horz
wmctrl -i -r $WID -e 0,1280,50,1250,1250
Run Code Online (Sandbox Code Playgroud)

但是第二个命令什么也不做,除非我在运行它之前手动移动或调整窗口大小。与 不同ewmhwmctrl如果窗口最大化,则永远不会按预期工作。wmctrl成功取消最大化窗口,但之后无法更改其位置或大小。

这在单监视器和三监视器 X 屏幕状态下均可重现。

此问题似乎并非特定于任何特定工具。例如,如果窗口只是未最大化但未手动移动/调整大小,则 xdotool 也无法更改窗口大小/位置。


到目前为止,我发现的唯一可靠的解决方法是手动、使用ewmh或取消最大化窗口,wmctrl然后手动更改窗口大小或手动稍微移动它。只有这样,我才能始终使用ewmh或移动或调整其大小wmctrl。但显然这不是可接受的解决方案。

即使窗口当前最大化,是否有可靠的方法来设置窗口几何形状?首选通过 Python 的方法,但使用 shell 命令的解决方案也可以。

Lis*_*yen 8

感谢 nm 评论我找到了解决方案。以下是我的 python脚本中的相关部分(它保存和恢复所有窗口的状态和几何形状,因此此示例取消最大化、取消映射和映射所有窗口):

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
Run Code Online (Sandbox Code Playgroud)

执行此代码后,可以为任何窗口设置窗口几何形状。all_win是所有窗口的列表,表示为填充有来自 的数据的自定义类对象列表ewmh.getClientList()。每个client.xwin = disp.create_resource_object("window", client.id)。等待映射/取消映射完成很重要,否则它将不可靠。此外,有必要限制轮询尝试,以防止无限循环,以防某些窗口意外映射或取消映射。


如果您不想一次重新配置很多窗口,使用 python xlib 模块进行取消映射和映射并没有明显的性能改进,那么使用 xdotool 会更容易:

from os import system
...
system("xdotool windowunmap --sync " + str(client.window.id))
system("xdotool windowmap   --sync " + str(client.window.id))
Run Code Online (Sandbox Code Playgroud)

如果您想在 shell 脚本中设置窗口几何形状,即使窗口最大化,以下示例也应该有效:

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
Run Code Online (Sandbox Code Playgroud)