Repository: qtile/qtile

Issue:
Bars not working on vertical displays using wayland
Hi, I tried to use a vertical monitor and stumbled across a strange error my bar is not usable like this.

I'm running Arch 5.16.5-zen1-1-zen
qtile pacman package version 0.20.0-1,
wlroots 0.15.1-2,
python-pywlroots 0.15.7-2

![buggyBar](https://user-images.githubusercontent.com/38183212/153052140-232383f9-6da0-46bd-bf81-002c2ed78f91.jpg)



Discussion:

Resolving patch:
diff --git a/libqtile/backend/wayland/core.py b/libqtile/backend/wayland/core.py
--- a/libqtile/backend/wayland/core.py
+++ b/libqtile/backend/wayland/core.py
@@ -873,14 +873,11 @@ def graceful_shutdown(self):
     def painter(self):
         return wlrq.Painter(self)
 
-    def output_from_wlr_output(self, wlr_output: wlrOutput) -> Output:
-        matched = []
-        for output in self.outputs:
-            if output.wlr_output == wlr_output:
-                matched.append(output)
-
-        assert len(matched) == 1
-        return matched[0]
+    def remove_output(self, output: Output) -> None:
+        self.outputs.remove(output)
+        if output is self._current_output:
+            self._current_output = self.outputs[0] if self.outputs else None
+            self.stack_windows()
 
     def keysym_from_name(self, name: str) -> int:
         """Get the keysym for a key from its name"""
diff --git a/libqtile/backend/wayland/output.py b/libqtile/backend/wayland/output.py
--- a/libqtile/backend/wayland/output.py
+++ b/libqtile/backend/wayland/output.py
@@ -57,7 +57,6 @@ def __init__(self, core: Core, wlr_output: wlrOutput):
         self.output_layout = self.core.output_layout
         self._damage: OutputDamage = OutputDamage(wlr_output)
         self.wallpaper = None
-        self.transform_matrix = wlr_output.transform_matrix
         self.x, self.y = self.output_layout.output_coords(wlr_output)
 
         self.add_listener(wlr_output.destroy_event, self._on_destroy)
@@ -77,8 +76,8 @@ def __init__(self, core: Core, wlr_output: wlrOutput):
                 wlr_output.set_custom_mode(640, 480, 0)
             wlr_output.commit()
 
-    def finalize(self):
-        self.core.outputs.remove(self)
+    def finalize(self) -> None:
+        self.core.remove_output(self)
         self.finalize_listeners()
 
     @property
@@ -115,13 +114,12 @@ def _on_frame(self, _listener, _data):
                 renderer = self.renderer
                 renderer.begin(wlr_output._ptr.width, wlr_output._ptr.height)
                 scale = wlr_output.scale
+                transform_matrix = wlr_output.transform_matrix
 
                 if self.wallpaper:
                     width, height = wlr_output.effective_resolution()
                     box = Box(0, 0, int(width * scale), int(height * scale))
-                    matrix = Matrix.project_box(
-                        box, wlr_output.transform, 0, wlr_output.transform_matrix
-                    )
+                    matrix = Matrix.project_box(box, 0, 0, transform_matrix)
                     renderer.render_texture_with_matrix(self.wallpaper, matrix, 1)
                 else:
                     renderer.clear([0, 0, 0, 1])
@@ -142,9 +140,7 @@ def _on_frame(self, _listener, _data):
                             int(window.width * scale),
                             int(window.height * scale),
                         )
-                        matrix = Matrix.project_box(
-                            box, wlr_output.transform, 0, wlr_output.transform_matrix
-                        )
+                        matrix = Matrix.project_box(box, 0, 0, transform_matrix)
                         renderer.render_texture_with_matrix(
                             window.texture, matrix, window.opacity
                         )
@@ -155,12 +151,13 @@ def _on_frame(self, _listener, _data):
                             window.x - self.x,  # layout coordinates -> output coordinates
                             window.y - self.y,
                             window.opacity,
-                            wlr_output.scale,
+                            scale,
+                            transform_matrix,
                         )
                         window.surface.for_each_surface(self._render_surface, rdata)
 
                 if self.core.live_dnd:
-                    self._render_dnd_icon(now)
+                    self._render_dnd_icon(self.core.live_dnd, now, scale, transform_matrix)
 
                 wlr_output.render_software_cursors(damage=damage)
                 renderer.end()
@@ -170,12 +167,11 @@ def _render_surface(self, surface: Surface, sx: int, sy: int, rdata: tuple) -> N
         if texture is None:
             return
 
-        now, window, wx, wy, opacity, scale = rdata
+        now, window, wx, wy, opacity, scale, transform_matrix = rdata
         x = (wx + sx) * scale
         y = (wy + sy) * scale
         width = surface.current.width * scale
         height = surface.current.height * scale
-        transform_matrix = self.transform_matrix
 
         if window.borderwidth:
             bw = int(window.borderwidth * scale)
@@ -221,15 +217,14 @@ def _render_surface(self, surface: Surface, sx: int, sy: int, rdata: tuple) -> N
         self.renderer.render_texture_with_matrix(texture, matrix, opacity)
         surface.send_frame_done(now)
 
-    def _render_dnd_icon(self, now: Timespec) -> None:
+    def _render_dnd_icon(
+        self, dnd: Dnd, now: Timespec, scale: float, transform_matrix: Matrix
+    ) -> None:
         """Render the drag-n-drop icon if there is one."""
-        dnd = self.core.live_dnd
-        assert dnd
         icon = dnd.wlr_drag.icon
         if icon.mapped:
             texture = icon.surface.get_texture()
             if texture:
-                scale = self.wlr_output.scale
                 box = Box(
                     int((dnd.x - self.x) * scale),
                     int((dnd.y - self.y) * scale),
@@ -237,7 +232,7 @@ def _render_dnd_icon(self, now: Timespec) -> None:
                     int(icon.surface.current.height * scale),
                 )
                 inverse = wlrOutput.transform_invert(icon.surface.current.transform)
-                matrix = Matrix.project_box(box, inverse, 0, self.transform_matrix)
+                matrix = Matrix.project_box(box, inverse, 0, transform_matrix)
                 self.renderer.render_texture_with_matrix(texture, matrix, 1)
                 icon.surface.send_frame_done(now)
 
@@ -247,7 +242,7 @@ def get_geometry(self) -> tuple[int, int, int, int]:
 
     def organise_layers(self) -> None:
         """Organise the positioning of layer shell surfaces."""
-        logger.info("Output: organising layers")
+        logger.debug("Output: organising layers")
         ow, oh = self.wlr_output.effective_resolution()
 
         for layer in self.layers:
diff --git a/libqtile/backend/wayland/window.py b/libqtile/backend/wayland/window.py
--- a/libqtile/backend/wayland/window.py
+++ b/libqtile/backend/wayland/window.py
@@ -943,8 +943,12 @@ def __init__(
             self.desired_height = 0
             if surface.output is None:
                 surface.output = core.output_layout.output_at(core.cursor.x, core.cursor.y)
-            self.output = core.output_from_wlr_output(surface.output)
-            self.screen = self.output.screen
+
+            output = surface.output.data
+            if output:
+                self.output = output
+                self.screen = self.output.screen
+
             self.mapped = True
             self._outputs.add(self.output)
 


Test patch: