如何解决使用 Python 管理多个 x11 窗口
我正在尝试创建一个类似于 Microsoft 的 FancyZones 的基于 Python 的窗口管理器。这个管理器的任务之一是允许用户创建窗口作为窗口可以“对齐”到的区域的模板。这个想法是我可以只允许用户创建多个窗口,并且在“保存”时,模块将缓存窗口几何图形以供以后捕捉。我遇到的问题是管理多个窗口。在我的程序中,'add' 关键字启动一个线程来处理单个窗口及其后续事件循环。单线程就可以了——我们可以在需要时缓存几何图形。然而,多个线程最终会导致程序陷入困境。
Q:
是否有我在此处缺少的设计范式可以使其具有高性能?
import json
import os
import sys
import threading
from Xlib import X
from Xlib.display import display
from Xlib.error import XError,ConnectionClosedError
HERE = os.path.abspath(os.path.dirname(__file__))
def active_window(display,window_id=None):
if not window_id:
window_id = display.screen().root.get_full_property(
display.intern_atom('_NET_ACTIVE_WINDOW'),X.AnyPropertyType
).value[0]
try:
return display.create_resource_object('window',window_id)
except XError:
return None
class Window:
def __init__(self,display,msg):
self.display = display
self.msg = msg
self.screen = self.display.screen()
self.window = self.screen.root.create_window(
10,10,500,250,1,self.screen.root_depth,background_pixel=self.screen.black_pixel,event_mask=X.ExposureMask | X.KeyPressMask,)
self.gc = self.window.create_gc(
background = self.screen.black_pixel,)
self.window.map()
def loop(self):
while True:
try:
e = self.display.next_event()
if e.type == X.Expose:
self.window.draw_text(self.gc,50,self.msg)
elif e.type == X.KeyPress:
raise SystemExit
except ConnectionClosedError:
# raised when X button is pressed
#
# Todo: figure out way to allow exit of single window without
# having to kill the entire application (currently get a
# "socket_error" if you try to add a window after exiting
# an already made window)
#
# for Now,just kill everything
os._exit(1)
@property
def _id(self):
return self.window.id
class ZoneBuilder:
def __init__(self) -> None:
self.zones = []
self.display = display()
self.screen = self.display.screen()
def _main_action(self):
return input(
'specify action:\n$ '
)
def main(self):
action = self._main_action()
if action == "add":
self.add
elif action == "done":
self.done
elif action == "exit":
self.terminate()
self.main()
@property
def done(self):
results = []
for zone,_ in self.zones:
window = active_window(self.display,zone._id)
pg = window.query_tree().parent.query_tree().parent.get_geometry()
results.append({
"x": pg.x,"y": pg.y,"width": pg.width,"height": pg.height
})
self._write(results)
self.terminate()
@property
def add(self):
window = Window(self.display,f"Zone {len(self.zones) + 1}")
thread = threading.Thread(target=window.loop)
thread.daemon = True
thread.start()
self.zones.append([window,thread])
def _read(self,path = os.path.join(HERE,"zones.json")):
with open(path,'r') as f:
return json.loads(f.read())
def _write(self,results,'w') as f:
f.write(json.dumps(results,indent=2,sort_keys=True))
def terminate(self):
sys.exit()
if __name__ == "__main__":
zb = ZoneBuilder()
zb.main()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。