We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Systray icon disappears with restart
As reported on IRC:
```
[08:11] <    elcaven> this morning I updated qtile from the qtile-git package from the AUR and since then it seems that my systray widget resets every time qtile restarts, so after a qtile restart the systray
                      is empty until a program spawns there again
[08:12] <    elcaven> there don't seem to be any related errors in the logfile, only one I see is "AttributeError: 'Screen' object has 
[20:53] < elParaguayo> | elcaven - interesting. That may be a side-effect of the config reloading code that was recently committed.
[21:09] <       mcol> What does it mean for the systray to reset? Can it persist state across restarts?
[21:14] < elParaguayo> | I'm guessing that the app is still open but the icon has disappeared from the tray
[21:22] < elParaguayo> | I wonder if SNI has that issue too...
[21:25] < elParaguayo> | No, SNI looks ok.
[21:25] < elParaguayo> | Tested with "restart" and "reload_config"
[21:27] < elParaguayo> | Confirmed, Systray icon disappears on reload_config even though app is open.
[21:28] < elParaguayo> | Icon doesn't disappear with "restart"
```

Tested on latest: 66ce6c28

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `libqtile/widget/systray.py`
Content:
```
1 # Copyright (c) 2010 Aldo Cortesi
2 # Copyright (c) 2010-2011 dequis
3 # Copyright (c) 2010, 2012 roger
4 # Copyright (c) 2011 Mounier Florian
5 # Copyright (c) 2011-2012, 2014 Tycho Andersen
6 # Copyright (c) 2012 dmpayton
7 # Copyright (c) 2012-2013 Craig Barnes
8 # Copyright (c) 2013 hbc
9 # Copyright (c) 2013 Tao Sauvage
10 # Copyright (c) 2014 Sean Vig
11 #
12 # Permission is hereby granted, free of charge, to any person obtaining a copy
13 # of this software and associated documentation files (the "Software"), to deal
14 # in the Software without restriction, including without limitation the rights
15 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 # copies of the Software, and to permit persons to whom the Software is
17 # furnished to do so, subject to the following conditions:
18 #
19 # The above copyright notice and this permission notice shall be included in
20 # all copies or substantial portions of the Software.
21 #
22 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 # SOFTWARE.
29 import xcffib
30 from xcffib.xproto import (
31     ClientMessageData,
32     ClientMessageEvent,
33     EventMask,
34     SetMode,
35 )
36 
37 from libqtile import bar
38 from libqtile.backend.x11 import window
39 from libqtile.widget import base
40 
41 XEMBED_PROTOCOL_VERSION = 0
42 
43 
44 class Icon(window._Window):
45     _window_mask = EventMask.StructureNotify | \
46         EventMask.PropertyChange | \
47         EventMask.Exposure
48 
49     def __init__(self, win, qtile, systray):
50         window._Window.__init__(self, win, qtile)
51         self.systray = systray
52         self.update_size()
53 
54     def update_size(self):
55         icon_size = self.systray.icon_size
56         self.update_hints()
57 
58         width = self.hints.get("min_width", icon_size)
59         height = self.hints.get("min_height", icon_size)
60 
61         width = max(width, icon_size)
62         height = max(height, icon_size)
63 
64         if height > icon_size:
65             width = width * icon_size // height
66             height = icon_size
67 
68         self.width = width
69         self.height = height
70         return False
71 
72     def handle_PropertyNotify(self, e):  # noqa: N802
73         name = self.qtile.core.conn.atoms.get_name(e.atom)
74         if name == "_XEMBED_INFO":
75             info = self.window.get_property('_XEMBED_INFO', unpack=int)
76             if info and info[1]:
77                 self.systray.bar.draw()
78 
79         return False
80 
81     def handle_DestroyNotify(self, event):  # noqa: N802
82         wid = event.window
83         del(self.qtile.windows_map[wid])
84         del(self.systray.icons[wid])
85         self.systray.bar.draw()
86         return False
87 
88     handle_UnmapNotify = handle_DestroyNotify  # noqa: N815
89 
90 
91 class Systray(window._Window, base._Widget):
92     """
93     A widget that manages system tray.
94 
95     .. note::
96         Icons will not render correctly where the bar/widget is
97         drawn with a semi-transparent background. Instead, icons
98         will be drawn with a transparent background.
99 
100         If using this widget it is therefore recommended to use
101         a fully opaque background colour or a fully transparent
102         one.
103     """
104 
105     _window_mask = EventMask.StructureNotify | \
106         EventMask.Exposure
107 
108     orientations = base.ORIENTATION_HORIZONTAL
109 
110     defaults = [
111         ('icon_size', 20, 'Icon width'),
112         ('padding', 5, 'Padding between icons'),
113     ]
114 
115     def __init__(self, **config):
116         base._Widget.__init__(self, bar.CALCULATED, **config)
117         self.add_defaults(Systray.defaults)
118         self.icons = {}
119         self.screen = 0
120 
121     def calculate_length(self):
122         width = sum(i.width for i in self.icons.values())
123         width += self.padding * len(self.icons)
124         return width
125 
126     def _configure(self, qtile, bar):
127         base._Widget._configure(self, qtile, bar)
128 
129         if self.configured:
130             return
131 
132         self.conn = conn = qtile.core.conn
133         win = conn.create_window(-1, -1, 1, 1)
134         window._Window.__init__(self, window.XWindow(conn, win.wid), qtile)
135         qtile.windows_map[win.wid] = self
136 
137         # Even when we have multiple "Screen"s, we are setting up as the system
138         # tray on a particular X display, that is the screen we need to
139         # reference in the atom
140         if qtile.current_screen:
141             self.screen = qtile.current_screen.index
142         self.bar = bar
143         atoms = conn.atoms
144 
145         # We need tray to tell icons which visual to use.
146         # This needs to be the same as the bar/widget.
147         # This mainly benefits transparent bars.
148         conn.conn.core.ChangeProperty(
149             xcffib.xproto.PropMode.Replace,
150             win.wid,
151             atoms["_NET_SYSTEM_TRAY_VISUAL"],
152             xcffib.xproto.Atom.VISUALID,
153             32,
154             1,
155             [self.drawer._visual.visual_id]
156         )
157 
158         conn.conn.core.SetSelectionOwner(
159             win.wid,
160             atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],
161             xcffib.CurrentTime
162         )
163         data = [
164             xcffib.CurrentTime,
165             atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],
166             win.wid, 0, 0
167         ]
168         union = ClientMessageData.synthetic(data, "I" * 5)
169         event = ClientMessageEvent.synthetic(
170             format=32,
171             window=qtile.core._root.wid,
172             type=atoms['MANAGER'],
173             data=union
174         )
175         qtile.core._root.send_event(event, mask=EventMask.StructureNotify)
176 
177     def handle_ClientMessage(self, event):  # noqa: N802
178         atoms = self.conn.atoms
179 
180         opcode = event.type
181         data = event.data.data32
182         message = data[1]
183         wid = data[2]
184 
185         parent = self.bar.window.window
186 
187         if opcode == atoms['_NET_SYSTEM_TRAY_OPCODE'] and message == 0:
188             w = window.XWindow(self.conn, wid)
189             icon = Icon(w, self.qtile, self)
190             self.icons[wid] = icon
191             self.qtile.windows_map[wid] = icon
192 
193             self.conn.conn.core.ChangeSaveSet(SetMode.Insert, wid)
194             self.conn.conn.core.ReparentWindow(wid, parent.wid, 0, 0)
195             self.conn.conn.flush()
196 
197             info = icon.window.get_property('_XEMBED_INFO', unpack=int)
198 
199             if not info:
200                 self.bar.draw()
201                 return False
202 
203             if info[1]:
204                 self.bar.draw()
205 
206         return False
207 
208     def draw(self):
209         xoffset = self.padding
210         self.drawer.clear(self.background or self.bar.background)
211         self.drawer.draw(offsetx=self.offset, width=self.length)
212         for pos, icon in enumerate(self.icons.values()):
213             icon.window.set_attribute(backpixmap=self.drawer.pixmap)
214             icon.place(
215                 self.offset + xoffset,
216                 self.bar.height // 2 - self.icon_size // 2,
217                 icon.width, self.icon_size,
218                 0,
219                 None
220             )
221             if icon.hidden:
222                 icon.unhide()
223                 data = [
224                     self.conn.atoms["_XEMBED_EMBEDDED_NOTIFY"],
225                     xcffib.xproto.Time.CurrentTime,
226                     0,
227                     self.bar.window.wid,
228                     XEMBED_PROTOCOL_VERSION
229                 ]
230                 u = xcffib.xproto.ClientMessageData.synthetic(data, "I" * 5)
231                 event = xcffib.xproto.ClientMessageEvent.synthetic(
232                     format=32,
233                     window=icon.wid,
234                     type=self.conn.atoms["_XEMBED"],
235                     data=u
236                 )
237                 self.window.send_event(event)
238 
239             xoffset += icon.width + self.padding
240 
241     def finalize(self):
242         base._Widget.finalize(self)
243         atoms = self.conn.atoms
244         self.conn.conn.core.SetSelectionOwner(
245             0,
246             atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],
247             xcffib.CurrentTime,
248         )
249         self.hide()
250
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/libqtile/widget/systray.py b/libqtile/widget/systray.py
--- a/libqtile/widget/systray.py
+++ b/libqtile/widget/systray.py
@@ -247,3 +247,11 @@
             xcffib.CurrentTime,
         )
         self.hide()
+
+        root = self.qtile.core._root.wid
+        for wid in self.icons:
+            self.conn.conn.core.ReparentWindow(wid, root, 0, 0)
+        self.conn.conn.flush()
+
+        del self.qtile.windows_map[self.wid]
+        self.conn.conn.core.DestroyWindow(self.wid)

{"golden_diff": "diff --git a/libqtile/widget/systray.py b/libqtile/widget/systray.py\n--- a/libqtile/widget/systray.py\n+++ b/libqtile/widget/systray.py\n@@ -247,3 +247,11 @@\n             xcffib.CurrentTime,\n         )\n         self.hide()\n+\n+        root = self.qtile.core._root.wid\n+        for wid in self.icons:\n+            self.conn.conn.core.ReparentWindow(wid, root, 0, 0)\n+        self.conn.conn.flush()\n+\n+        del self.qtile.windows_map[self.wid]\n+        self.conn.conn.core.DestroyWindow(self.wid)\n", "issue": "Systray icon disappears with restart\nAs reported on IRC:\r\n```\r\n[08:11] <    elcaven> this morning I updated qtile from the qtile-git package from the AUR and since then it seems that my systray widget resets every time qtile restarts, so after a qtile restart the systray\r\n                      is empty until a program spawns there again\r\n[08:12] <    elcaven> there don't seem to be any related errors in the logfile, only one I see is \"AttributeError: 'Screen' object has \r\n[20:53] < elParaguayo> | elcaven - interesting. That may be a side-effect of the config reloading code that was recently committed.\r\n[21:09] <       mcol> What does it mean for the systray to reset? Can it persist state across restarts?\r\n[21:14] < elParaguayo> | I'm guessing that the app is still open but the icon has disappeared from the tray\r\n[21:22] < elParaguayo> | I wonder if SNI has that issue too...\r\n[21:25] < elParaguayo> | No, SNI looks ok.\r\n[21:25] < elParaguayo> | Tested with \"restart\" and \"reload_config\"\r\n[21:27] < elParaguayo> | Confirmed, Systray icon disappears on reload_config even though app is open.\r\n[21:28] < elParaguayo> | Icon doesn't disappear with \"restart\"\r\n```\r\n\r\nTested on latest: 66ce6c28\n", "before_files": [{"content": "# Copyright (c) 2010 Aldo Cortesi\n# Copyright (c) 2010-2011 dequis\n# Copyright (c) 2010, 2012 roger\n# Copyright (c) 2011 Mounier Florian\n# Copyright (c) 2011-2012, 2014 Tycho Andersen\n# Copyright (c) 2012 dmpayton\n# Copyright (c) 2012-2013 Craig Barnes\n# Copyright (c) 2013 hbc\n# Copyright (c) 2013 Tao Sauvage\n# Copyright (c) 2014 Sean Vig\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\nimport xcffib\nfrom xcffib.xproto import (\n    ClientMessageData,\n    ClientMessageEvent,\n    EventMask,\n    SetMode,\n)\n\nfrom libqtile import bar\nfrom libqtile.backend.x11 import window\nfrom libqtile.widget import base\n\nXEMBED_PROTOCOL_VERSION = 0\n\n\nclass Icon(window._Window):\n    _window_mask = EventMask.StructureNotify | \\\n        EventMask.PropertyChange | \\\n        EventMask.Exposure\n\n    def __init__(self, win, qtile, systray):\n        window._Window.__init__(self, win, qtile)\n        self.systray = systray\n        self.update_size()\n\n    def update_size(self):\n        icon_size = self.systray.icon_size\n        self.update_hints()\n\n        width = self.hints.get(\"min_width\", icon_size)\n        height = self.hints.get(\"min_height\", icon_size)\n\n        width = max(width, icon_size)\n        height = max(height, icon_size)\n\n        if height > icon_size:\n            width = width * icon_size // height\n            height = icon_size\n\n        self.width = width\n        self.height = height\n        return False\n\n    def handle_PropertyNotify(self, e):  # noqa: N802\n        name = self.qtile.core.conn.atoms.get_name(e.atom)\n        if name == \"_XEMBED_INFO\":\n            info = self.window.get_property('_XEMBED_INFO', unpack=int)\n            if info and info[1]:\n                self.systray.bar.draw()\n\n        return False\n\n    def handle_DestroyNotify(self, event):  # noqa: N802\n        wid = event.window\n        del(self.qtile.windows_map[wid])\n        del(self.systray.icons[wid])\n        self.systray.bar.draw()\n        return False\n\n    handle_UnmapNotify = handle_DestroyNotify  # noqa: N815\n\n\nclass Systray(window._Window, base._Widget):\n    \"\"\"\n    A widget that manages system tray.\n\n    .. note::\n        Icons will not render correctly where the bar/widget is\n        drawn with a semi-transparent background. Instead, icons\n        will be drawn with a transparent background.\n\n        If using this widget it is therefore recommended to use\n        a fully opaque background colour or a fully transparent\n        one.\n    \"\"\"\n\n    _window_mask = EventMask.StructureNotify | \\\n        EventMask.Exposure\n\n    orientations = base.ORIENTATION_HORIZONTAL\n\n    defaults = [\n        ('icon_size', 20, 'Icon width'),\n        ('padding', 5, 'Padding between icons'),\n    ]\n\n    def __init__(self, **config):\n        base._Widget.__init__(self, bar.CALCULATED, **config)\n        self.add_defaults(Systray.defaults)\n        self.icons = {}\n        self.screen = 0\n\n    def calculate_length(self):\n        width = sum(i.width for i in self.icons.values())\n        width += self.padding * len(self.icons)\n        return width\n\n    def _configure(self, qtile, bar):\n        base._Widget._configure(self, qtile, bar)\n\n        if self.configured:\n            return\n\n        self.conn = conn = qtile.core.conn\n        win = conn.create_window(-1, -1, 1, 1)\n        window._Window.__init__(self, window.XWindow(conn, win.wid), qtile)\n        qtile.windows_map[win.wid] = self\n\n        # Even when we have multiple \"Screen\"s, we are setting up as the system\n        # tray on a particular X display, that is the screen we need to\n        # reference in the atom\n        if qtile.current_screen:\n            self.screen = qtile.current_screen.index\n        self.bar = bar\n        atoms = conn.atoms\n\n        # We need tray to tell icons which visual to use.\n        # This needs to be the same as the bar/widget.\n        # This mainly benefits transparent bars.\n        conn.conn.core.ChangeProperty(\n            xcffib.xproto.PropMode.Replace,\n            win.wid,\n            atoms[\"_NET_SYSTEM_TRAY_VISUAL\"],\n            xcffib.xproto.Atom.VISUALID,\n            32,\n            1,\n            [self.drawer._visual.visual_id]\n        )\n\n        conn.conn.core.SetSelectionOwner(\n            win.wid,\n            atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],\n            xcffib.CurrentTime\n        )\n        data = [\n            xcffib.CurrentTime,\n            atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],\n            win.wid, 0, 0\n        ]\n        union = ClientMessageData.synthetic(data, \"I\" * 5)\n        event = ClientMessageEvent.synthetic(\n            format=32,\n            window=qtile.core._root.wid,\n            type=atoms['MANAGER'],\n            data=union\n        )\n        qtile.core._root.send_event(event, mask=EventMask.StructureNotify)\n\n    def handle_ClientMessage(self, event):  # noqa: N802\n        atoms = self.conn.atoms\n\n        opcode = event.type\n        data = event.data.data32\n        message = data[1]\n        wid = data[2]\n\n        parent = self.bar.window.window\n\n        if opcode == atoms['_NET_SYSTEM_TRAY_OPCODE'] and message == 0:\n            w = window.XWindow(self.conn, wid)\n            icon = Icon(w, self.qtile, self)\n            self.icons[wid] = icon\n            self.qtile.windows_map[wid] = icon\n\n            self.conn.conn.core.ChangeSaveSet(SetMode.Insert, wid)\n            self.conn.conn.core.ReparentWindow(wid, parent.wid, 0, 0)\n            self.conn.conn.flush()\n\n            info = icon.window.get_property('_XEMBED_INFO', unpack=int)\n\n            if not info:\n                self.bar.draw()\n                return False\n\n            if info[1]:\n                self.bar.draw()\n\n        return False\n\n    def draw(self):\n        xoffset = self.padding\n        self.drawer.clear(self.background or self.bar.background)\n        self.drawer.draw(offsetx=self.offset, width=self.length)\n        for pos, icon in enumerate(self.icons.values()):\n            icon.window.set_attribute(backpixmap=self.drawer.pixmap)\n            icon.place(\n                self.offset + xoffset,\n                self.bar.height // 2 - self.icon_size // 2,\n                icon.width, self.icon_size,\n                0,\n                None\n            )\n            if icon.hidden:\n                icon.unhide()\n                data = [\n                    self.conn.atoms[\"_XEMBED_EMBEDDED_NOTIFY\"],\n                    xcffib.xproto.Time.CurrentTime,\n                    0,\n                    self.bar.window.wid,\n                    XEMBED_PROTOCOL_VERSION\n                ]\n                u = xcffib.xproto.ClientMessageData.synthetic(data, \"I\" * 5)\n                event = xcffib.xproto.ClientMessageEvent.synthetic(\n                    format=32,\n                    window=icon.wid,\n                    type=self.conn.atoms[\"_XEMBED\"],\n                    data=u\n                )\n                self.window.send_event(event)\n\n            xoffset += icon.width + self.padding\n\n    def finalize(self):\n        base._Widget.finalize(self)\n        atoms = self.conn.atoms\n        self.conn.conn.core.SetSelectionOwner(\n            0,\n            atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],\n            xcffib.CurrentTime,\n        )\n        self.hide()\n", "path": "libqtile/widget/systray.py"}], "after_files": [{"content": "# Copyright (c) 2010 Aldo Cortesi\n# Copyright (c) 2010-2011 dequis\n# Copyright (c) 2010, 2012 roger\n# Copyright (c) 2011 Mounier Florian\n# Copyright (c) 2011-2012, 2014 Tycho Andersen\n# Copyright (c) 2012 dmpayton\n# Copyright (c) 2012-2013 Craig Barnes\n# Copyright (c) 2013 hbc\n# Copyright (c) 2013 Tao Sauvage\n# Copyright (c) 2014 Sean Vig\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\nimport xcffib\nfrom xcffib.xproto import (\n    ClientMessageData,\n    ClientMessageEvent,\n    EventMask,\n    SetMode,\n)\n\nfrom libqtile import bar\nfrom libqtile.backend.x11 import window\nfrom libqtile.widget import base\n\nXEMBED_PROTOCOL_VERSION = 0\n\n\nclass Icon(window._Window):\n    _window_mask = EventMask.StructureNotify | \\\n        EventMask.PropertyChange | \\\n        EventMask.Exposure\n\n    def __init__(self, win, qtile, systray):\n        window._Window.__init__(self, win, qtile)\n        self.systray = systray\n        self.update_size()\n\n    def update_size(self):\n        icon_size = self.systray.icon_size\n        self.update_hints()\n\n        width = self.hints.get(\"min_width\", icon_size)\n        height = self.hints.get(\"min_height\", icon_size)\n\n        width = max(width, icon_size)\n        height = max(height, icon_size)\n\n        if height > icon_size:\n            width = width * icon_size // height\n            height = icon_size\n\n        self.width = width\n        self.height = height\n        return False\n\n    def handle_PropertyNotify(self, e):  # noqa: N802\n        name = self.qtile.core.conn.atoms.get_name(e.atom)\n        if name == \"_XEMBED_INFO\":\n            info = self.window.get_property('_XEMBED_INFO', unpack=int)\n            if info and info[1]:\n                self.systray.bar.draw()\n\n        return False\n\n    def handle_DestroyNotify(self, event):  # noqa: N802\n        wid = event.window\n        del(self.qtile.windows_map[wid])\n        del(self.systray.icons[wid])\n        self.systray.bar.draw()\n        return False\n\n    handle_UnmapNotify = handle_DestroyNotify  # noqa: N815\n\n\nclass Systray(window._Window, base._Widget):\n    \"\"\"\n    A widget that manages system tray.\n\n    .. note::\n        Icons will not render correctly where the bar/widget is\n        drawn with a semi-transparent background. Instead, icons\n        will be drawn with a transparent background.\n\n        If using this widget it is therefore recommended to use\n        a fully opaque background colour or a fully transparent\n        one.\n    \"\"\"\n\n    _window_mask = EventMask.StructureNotify | \\\n        EventMask.Exposure\n\n    orientations = base.ORIENTATION_HORIZONTAL\n\n    defaults = [\n        ('icon_size', 20, 'Icon width'),\n        ('padding', 5, 'Padding between icons'),\n    ]\n\n    def __init__(self, **config):\n        base._Widget.__init__(self, bar.CALCULATED, **config)\n        self.add_defaults(Systray.defaults)\n        self.icons = {}\n        self.screen = 0\n\n    def calculate_length(self):\n        width = sum(i.width for i in self.icons.values())\n        width += self.padding * len(self.icons)\n        return width\n\n    def _configure(self, qtile, bar):\n        base._Widget._configure(self, qtile, bar)\n\n        if self.configured:\n            return\n\n        self.conn = conn = qtile.core.conn\n        win = conn.create_window(-1, -1, 1, 1)\n        window._Window.__init__(self, window.XWindow(conn, win.wid), qtile)\n        qtile.windows_map[win.wid] = self\n\n        # Even when we have multiple \"Screen\"s, we are setting up as the system\n        # tray on a particular X display, that is the screen we need to\n        # reference in the atom\n        if qtile.current_screen:\n            self.screen = qtile.current_screen.index\n        self.bar = bar\n        atoms = conn.atoms\n\n        # We need tray to tell icons which visual to use.\n        # This needs to be the same as the bar/widget.\n        # This mainly benefits transparent bars.\n        conn.conn.core.ChangeProperty(\n            xcffib.xproto.PropMode.Replace,\n            win.wid,\n            atoms[\"_NET_SYSTEM_TRAY_VISUAL\"],\n            xcffib.xproto.Atom.VISUALID,\n            32,\n            1,\n            [self.drawer._visual.visual_id]\n        )\n\n        conn.conn.core.SetSelectionOwner(\n            win.wid,\n            atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],\n            xcffib.CurrentTime\n        )\n        data = [\n            xcffib.CurrentTime,\n            atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],\n            win.wid, 0, 0\n        ]\n        union = ClientMessageData.synthetic(data, \"I\" * 5)\n        event = ClientMessageEvent.synthetic(\n            format=32,\n            window=qtile.core._root.wid,\n            type=atoms['MANAGER'],\n            data=union\n        )\n        qtile.core._root.send_event(event, mask=EventMask.StructureNotify)\n\n    def handle_ClientMessage(self, event):  # noqa: N802\n        atoms = self.conn.atoms\n\n        opcode = event.type\n        data = event.data.data32\n        message = data[1]\n        wid = data[2]\n\n        parent = self.bar.window.window\n\n        if opcode == atoms['_NET_SYSTEM_TRAY_OPCODE'] and message == 0:\n            w = window.XWindow(self.conn, wid)\n            icon = Icon(w, self.qtile, self)\n            self.icons[wid] = icon\n            self.qtile.windows_map[wid] = icon\n\n            self.conn.conn.core.ChangeSaveSet(SetMode.Insert, wid)\n            self.conn.conn.core.ReparentWindow(wid, parent.wid, 0, 0)\n            self.conn.conn.flush()\n\n            info = icon.window.get_property('_XEMBED_INFO', unpack=int)\n\n            if not info:\n                self.bar.draw()\n                return False\n\n            if info[1]:\n                self.bar.draw()\n\n        return False\n\n    def draw(self):\n        xoffset = self.padding\n        self.drawer.clear(self.background or self.bar.background)\n        self.drawer.draw(offsetx=self.offset, width=self.length)\n        for pos, icon in enumerate(self.icons.values()):\n            icon.window.set_attribute(backpixmap=self.drawer.pixmap)\n            icon.place(\n                self.offset + xoffset,\n                self.bar.height // 2 - self.icon_size // 2,\n                icon.width, self.icon_size,\n                0,\n                None\n            )\n            if icon.hidden:\n                icon.unhide()\n                data = [\n                    self.conn.atoms[\"_XEMBED_EMBEDDED_NOTIFY\"],\n                    xcffib.xproto.Time.CurrentTime,\n                    0,\n                    self.bar.window.wid,\n                    XEMBED_PROTOCOL_VERSION\n                ]\n                u = xcffib.xproto.ClientMessageData.synthetic(data, \"I\" * 5)\n                event = xcffib.xproto.ClientMessageEvent.synthetic(\n                    format=32,\n                    window=icon.wid,\n                    type=self.conn.atoms[\"_XEMBED\"],\n                    data=u\n                )\n                self.window.send_event(event)\n\n            xoffset += icon.width + self.padding\n\n    def finalize(self):\n        base._Widget.finalize(self)\n        atoms = self.conn.atoms\n        self.conn.conn.core.SetSelectionOwner(\n            0,\n            atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],\n            xcffib.CurrentTime,\n        )\n        self.hide()\n\n        root = self.qtile.core._root.wid\n        for wid in self.icons:\n            self.conn.conn.core.ReparentWindow(wid, root, 0, 0)\n        self.conn.conn.flush()\n\n        del self.qtile.windows_map[self.wid]\n        self.conn.conn.core.DestroyWindow(self.wid)\n", "path": "libqtile/widget/systray.py"}]}