我正在尝试开发一个简单的跨平台壁纸管理器,但我无法找到任何方法将我的PyQt窗口放在当前的壁纸和桌面图标之间,使用XLib (在windows和macOS上--它更简单、工作更完美)。
这对肉桂有效(只需模拟一下点击),而不适用于GNOME。有人能帮我或者给我点线索吗?(我提供所有这些代码只是为了提供一个最小的可执行部分,但关键部分,我想,就在'if‘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)发布于 2022-12-02 22:27:47
尤里卡!上一个Ubuntu版本(22.04)似乎是自己带来了解决方案。它现在有一个“层”的桌面图标,你可以与之互动。这也给了我一条线索,可以在薄荷/肉桂上找到更聪明的解决方案(其他操作系统上的测试仍在等待中)。对于那些有同样问题的人来说,这段代码似乎是正常的:
import time
import Xlib.display
import ewmh
import pywinctl
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.id)
w.unmap()
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()
w.map()
# This will try to raise the desktop icons layer on top of the window
# Ubuntu: "@!0,0;BDHF" is the new desktop icons NG extension
# Mint: "Desktop" name is language-dependent. Using its class (nemo-desktop)
desktop = _xlibGetAllWindows(title="@!0,0;BDHF", klass=('nemo-desktop', 'Nemo-desktop'))
for d in desktop:
w = DISP.create_resource_object('window', d)
w.raise_window()
return '_NET_WM_WINDOW_TYPE_DESKTOP' in EWMH.getWmWindowType(hWnd, str=True)
def bringBack(hWnd):
w = DISP.create_resource_object('window', hWnd.id)
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=None, title: str = "", klass=None):
parent = parent or 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 and not klass:
return allWindows
else:
return [window for window in allWindows if ((title and window.get_wm_name() == title) or
(klass and window.get_wm_class() == klass))]
hWnd = pywinctl.getActiveWindow()
sendBehind(hWnd._hWnd)
time.sleep(3)
bringBack(hWnd._hWnd)https://stackoverflow.com/questions/71241339
复制相似问题