微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Python 管理多个 x11 窗口

如何解决使用 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 举报,一经查实,本站将立刻删除。