【发布时间】:2022-12-03 10:42:34
【问题描述】:
我正在尝试开发一个简单的跨平台壁纸管理器,但我无法找到任何方法使用 XLib 将我的 PyQt 窗口放置在当前壁纸和桌面图标之间(在 Windows 和 macOS 上它更容易并且工作完美) .
这可以在 Cinnamon 上正常工作(只需模拟点击一下即可),但在 GNOME 上不行。任何人都可以帮助或给我任何线索吗? (我提供所有这些代码只是为了提供最小的可执行部分,但我想关键部分就在“如果“GNOME”...”这句话之后)
import os
import time
import Xlib
import ewmh
import pywinctl
from pynput import mouse
DISP = Xlib.display.Display()
SCREEN = DISP.screen()
ROOT = DISP.screen().root
EWMH = ewmh.EWMH(_display=DISP, root=ROOT)
def sendBehind(hWnd):
w = DISP.create_resource_object('window', hWnd)
w.change_property(DISP.intern_atom('_NET_WM_STATE', False), Xlib.Xatom.ATOM, 32, [DISP.intern_atom('_NET_WM_STATE_BELOW', False), ], Xlib.X.PropModeReplace)
w.change_property(DISP.intern_atom('_NET_WM_STATE', False), Xlib.Xatom.ATOM, 32, [DISP.intern_atom('_NET_WM_STATE_SKIP_TASKBAR', False), ], Xlib.X.PropModeAppend)
w.change_property(DISP.intern_atom('_NET_WM_STATE', False), Xlib.Xatom.ATOM, 32, [DISP.intern_atom('_NET_WM_STATE_SKIP_PAGER', False), ], Xlib.X.PropModeAppend)
DISP.flush()
# This sends window below all others, but not behind the desktop icons
w.change_property(DISP.intern_atom('_NET_WM_WINDOW_TYPE', False), Xlib.Xatom.ATOM, 32, [DISP.intern_atom('_NET_WM_WINDOW_TYPE_DESKTOP', False), ],Xlib.X.PropModeReplace)
DISP.flush()
if "GNOME" in os.environ.get('XDG_CURRENT_DESKTOP', ""):
# This sends the window "too far behind" (below all others, including Wallpaper, like unmapped)
# Trying to figure out how to raise it on top of wallpaper but behind desktop icons
desktop = _xlibGetAllWindows(title="gnome-shell")
if desktop:
w.reparent(desktop[-1], 0, 0)
DISP.flush()
else:
# Mint/Cinnamon: just clicking on the desktop, it raises, sending the window/wallpaper to the bottom!
m = mouse.Controller()
m.move(SCREEN.width_in_pixels - 1, 100)
m.click(mouse.Button.left, 1)
return '_NET_WM_WINDOW_TYPE_DESKTOP' in EWMH.getWmWindowType(hWnd, str=True)
def bringBack(hWnd, parent):
w = DISP.create_resource_object('window', hWnd)
if parent:
w.reparent(parent, 0, 0)
DISP.flush()
w.unmap()
w.change_property(DISP.intern_atom('_NET_WM_WINDOW_TYPE', False), Xlib.Xatom.ATOM,
32, [DISP.intern_atom('_NET_WM_WINDOW_TYPE_NORMAL', False), ],
Xlib.X.PropModeReplace)
DISP.flush()
w.change_property(DISP.intern_atom('_NET_WM_STATE', False), Xlib.Xatom.ATOM,
32, [DISP.intern_atom('_NET_WM_STATE_FOCUSED', False), ],
Xlib.X.PropModeReplace)
DISP.flush()
w.map()
EWMH.setActiveWindow(hWnd)
EWMH.display.flush()
return '_NET_WM_WINDOW_TYPE_NORMAL' in EWMH.getWmWindowType(hWnd, str=True)
def _xlibGetAllWindows(parent: int = None, title: str = ""):
if not parent:
parent = ROOT
allWindows = [parent]
def findit(hwnd):
query = hwnd.query_tree()
for child in query.children:
allWindows.append(child)
findit(child)
findit(parent)
if not title:
matches = allWindows
else:
matches = []
for w in allWindows:
if w.get_wm_name() == title:
matches.append(w)
return matches
hWnd = pywinctl.getActiveWindow()
parent = hWnd._hWnd.query_tree().parent
sendBehind(hWnd._hWnd)
time.sleep(3)
bringBack(hWnd._hWnd, parent)
【问题讨论】:
-
所以你是说你可以在壁纸和 Windows 中的桌面图标之间放置一个窗口?
-
确切地。在 windows、macOs 和 cinnamon 上,但在 GNOME 中不行。有兴趣的可以看看:github.com/Kalmat/PyWinCtl
-
在我的 Ubuntu 上,这会立即关闭我关注的窗口;您可能已经警告过我们 :-)。另外,你忘了
import os。 -
@Kalma 太酷了!感谢您的链接 :)
-
所以,为了澄清起见,您希望您的窗口看起来像this,它在桌面上的图标后面,但在墙纸前面? (该图像经过编辑以进行演示;不幸的是我没有让您的代码正常工作)。
标签: python ubuntu pyqt5 gnome xlib