We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bad icon scaling in Systray widget
# Issue description
1. I added the system tray widget to my qtile bar with an icon size of 20.
2. I currently use the icon set Papirus Dark.
3. I launched the `nm-applet` through the autostart script and I obtained a really small icon for the `nm-applet` as you can see in the following image: 

![image](https://user-images.githubusercontent.com/31258166/116829694-d0a09500-ab6a-11eb-805e-8f0e6a8cb91c.png)

The previous small icon also happened if I launched `nm-applet` through the terminal. 

One way I found to correct it was to setting the **icon size for the system tray to 16**. With this icon size, I obtained the following good results:

![image](https://user-images.githubusercontent.com/31258166/116829734-2412e300-ab6b-11eb-9687-e7121be99d21.png)

# Qtile version
`qtile 0.17.0`

# Configuration

My configuration can be found in the following [dotfiles](https://github.com/juanscr/dotfiles/tree/master/.config/qtile)


--- 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         try:
59             width = self.hints["min_width"]
60             height = self.hints["min_height"]
61         except KeyError:
62             width = icon_size
63             height = icon_size
64 
65         if height > icon_size:
66             width = width * icon_size // height
67             height = icon_size
68         if height <= 0:
69             width = icon_size
70             height = icon_size
71 
72         self.width = width
73         self.height = height
74         return False
75 
76     def handle_PropertyNotify(self, e):  # noqa: N802
77         name = self.qtile.core.conn.atoms.get_name(e.atom)
78         if name == "_XEMBED_INFO":
79             info = self.window.get_property('_XEMBED_INFO', unpack=int)
80             if info and info[1]:
81                 self.systray.bar.draw()
82 
83         return False
84 
85     def handle_DestroyNotify(self, event):  # noqa: N802
86         wid = event.window
87         del(self.qtile.windows_map[wid])
88         del(self.systray.icons[wid])
89         self.systray.bar.draw()
90         return False
91 
92     handle_UnmapNotify = handle_DestroyNotify  # noqa: N815
93 
94 
95 class Systray(window._Window, base._Widget):
96     """A widget that manages system tray"""
97 
98     _window_mask = EventMask.StructureNotify | \
99         EventMask.Exposure
100 
101     orientations = base.ORIENTATION_HORIZONTAL
102 
103     defaults = [
104         ('icon_size', 20, 'Icon width'),
105         ('padding', 5, 'Padding between icons'),
106     ]
107 
108     def __init__(self, **config):
109         base._Widget.__init__(self, bar.CALCULATED, **config)
110         self.add_defaults(Systray.defaults)
111         self.icons = {}
112         self.screen = 0
113 
114     def calculate_length(self):
115         width = sum(i.width for i in self.icons.values())
116         width += self.padding * len(self.icons)
117         return width
118 
119     def _configure(self, qtile, bar):
120         base._Widget._configure(self, qtile, bar)
121 
122         if self.configured:
123             return
124 
125         self.conn = conn = qtile.core.conn
126         win = conn.create_window(-1, -1, 1, 1)
127         window._Window.__init__(self, window.XWindow(conn, win.wid), qtile)
128         qtile.windows_map[win.wid] = self
129 
130         # Even when we have multiple "Screen"s, we are setting up as the system
131         # tray on a particular X display, that is the screen we need to
132         # reference in the atom
133         if qtile.current_screen:
134             self.screen = qtile.current_screen.index
135         self.bar = bar
136         atoms = conn.atoms
137 
138         conn.conn.core.SetSelectionOwner(
139             win.wid,
140             atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],
141             xcffib.CurrentTime
142         )
143         data = [
144             xcffib.CurrentTime,
145             atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],
146             win.wid, 0, 0
147         ]
148         union = ClientMessageData.synthetic(data, "I" * 5)
149         event = ClientMessageEvent.synthetic(
150             format=32,
151             window=qtile.core._root.wid,
152             type=atoms['MANAGER'],
153             data=union
154         )
155         qtile.core._root.send_event(event, mask=EventMask.StructureNotify)
156 
157     def handle_ClientMessage(self, event):  # noqa: N802
158         atoms = self.conn.atoms
159 
160         opcode = event.type
161         data = event.data.data32
162         message = data[1]
163         wid = data[2]
164 
165         parent = self.bar.window.window
166 
167         if opcode == atoms['_NET_SYSTEM_TRAY_OPCODE'] and message == 0:
168             w = window.XWindow(self.conn, wid)
169             icon = Icon(w, self.qtile, self)
170             self.icons[wid] = icon
171             self.qtile.windows_map[wid] = icon
172 
173             self.conn.conn.core.ChangeSaveSet(SetMode.Insert, wid)
174             self.conn.conn.core.ReparentWindow(wid, parent.wid, 0, 0)
175             self.conn.conn.flush()
176 
177             info = icon.window.get_property('_XEMBED_INFO', unpack=int)
178 
179             if not info:
180                 self.bar.draw()
181                 return False
182 
183             if info[1]:
184                 self.bar.draw()
185 
186         return False
187 
188     def draw(self):
189         xoffset = self.padding
190         self.drawer.clear(self.background or self.bar.background)
191         self.drawer.draw(offsetx=self.offset, width=self.length)
192         for pos, icon in enumerate(self.icons.values()):
193             icon.window.set_attribute(backpixmap=self.drawer.pixmap)
194             icon.place(
195                 self.offset + xoffset,
196                 self.bar.height // 2 - self.icon_size // 2,
197                 icon.width, self.icon_size,
198                 0,
199                 None
200             )
201             if icon.hidden:
202                 icon.unhide()
203                 data = [
204                     self.conn.atoms["_XEMBED_EMBEDDED_NOTIFY"],
205                     xcffib.xproto.Time.CurrentTime,
206                     0,
207                     self.bar.window.wid,
208                     XEMBED_PROTOCOL_VERSION
209                 ]
210                 u = xcffib.xproto.ClientMessageData.synthetic(data, "I" * 5)
211                 event = xcffib.xproto.ClientMessageEvent.synthetic(
212                     format=32,
213                     window=icon.wid,
214                     type=self.conn.atoms["_XEMBED"],
215                     data=u
216                 )
217                 self.window.send_event(event)
218 
219             xoffset += icon.width + self.padding
220 
221     def finalize(self):
222         base._Widget.finalize(self)
223         atoms = self.conn.atoms
224         self.conn.conn.core.SetSelectionOwner(
225             0,
226             atoms['_NET_SYSTEM_TRAY_S{:d}'.format(self.screen)],
227             xcffib.CurrentTime,
228         )
229         self.hide()
230
```
--- 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
@@ -55,19 +55,15 @@
         icon_size = self.systray.icon_size
         self.update_hints()
 
-        try:
-            width = self.hints["min_width"]
-            height = self.hints["min_height"]
-        except KeyError:
-            width = icon_size
-            height = icon_size
+        width = self.hints.get("min_width", icon_size)
+        height = self.hints.get("min_height", icon_size)
+
+        width = max(width, icon_size)
+        height = max(height, icon_size)
 
         if height > icon_size:
             width = width * icon_size // height
             height = icon_size
-        if height <= 0:
-            width = icon_size
-            height = icon_size
 
         self.width = width
         self.height = height

{"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@@ -55,19 +55,15 @@\n         icon_size = self.systray.icon_size\n         self.update_hints()\n \n-        try:\n-            width = self.hints[\"min_width\"]\n-            height = self.hints[\"min_height\"]\n-        except KeyError:\n-            width = icon_size\n-            height = icon_size\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-        if height <= 0:\n-            width = icon_size\n-            height = icon_size\n \n         self.width = width\n         self.height = height\n", "issue": "Bad icon scaling in Systray widget\n# Issue description\r\n1. I added the system tray widget to my qtile bar with an icon size of 20.\r\n2. I currently use the icon set Papirus Dark.\r\n3. I launched the `nm-applet` through the autostart script and I obtained a really small icon for the `nm-applet` as you can see in the following image: \r\n\r\n![image](https://user-images.githubusercontent.com/31258166/116829694-d0a09500-ab6a-11eb-805e-8f0e6a8cb91c.png)\r\n\r\nThe previous small icon also happened if I launched `nm-applet` through the terminal. \r\n\r\nOne way I found to correct it was to setting the **icon size for the system tray to 16**. With this icon size, I obtained the following good results:\r\n\r\n![image](https://user-images.githubusercontent.com/31258166/116829734-2412e300-ab6b-11eb-9687-e7121be99d21.png)\r\n\r\n# Qtile version\r\n`qtile 0.17.0`\r\n\r\n# Configuration\r\n\r\nMy configuration can be found in the following [dotfiles](https://github.com/juanscr/dotfiles/tree/master/.config/qtile)\r\n\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        try:\n            width = self.hints[\"min_width\"]\n            height = self.hints[\"min_height\"]\n        except KeyError:\n            width = icon_size\n            height = icon_size\n\n        if height > icon_size:\n            width = width * icon_size // height\n            height = icon_size\n        if height <= 0:\n            width = icon_size\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    \"\"\"A widget that manages system tray\"\"\"\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        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    \"\"\"A widget that manages system tray\"\"\"\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        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"}]}