Ejemplo n.º 1
0
    def _render_surface(self, surface: Surface, sx: int, sy: int,
                        rdata: tuple) -> None:
        texture = surface.get_texture()
        if texture is None:
            return

        now, window, wx, wy, opacity, scale = 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)

            if surface == window.surface.surface:
                outer_w = width + bw * 2
                outer_h = height + bw * 2
                num = len(window.bordercolor)
                bws = [bw // num] * num
                for i in range(bw % num):
                    bws[i] += 1
                coord = 0
                for i, bc in enumerate(window.bordercolor):
                    border = Box(
                        int(x + coord),
                        int(y + coord),
                        int(outer_w - coord * 2),
                        int(bws[i]),
                    )
                    self.renderer.render_rect(border, bc,
                                              transform_matrix)  # Top border
                    border.y = int(y + outer_h - bws[i] - coord)
                    self.renderer.render_rect(
                        border, bc, transform_matrix)  # Bottom border
                    border.y = int(y + coord)
                    border.width = int(bws[i])
                    border.height = int(outer_h - coord * 2)
                    self.renderer.render_rect(border, bc,
                                              transform_matrix)  # Left border
                    border.x = int(x + outer_w - bws[i] - coord)
                    self.renderer.render_rect(border, bc,
                                              transform_matrix)  # Right border
                    coord += bws[i]

            x += bw
            y += bw

        box = Box(
            int(x),
            int(y),
            int(width),
            int(height),
        )

        inverse = wlrOutput.transform_invert(surface.current.transform)
        matrix = Matrix.project_box(box, inverse, 0, transform_matrix)
        self.renderer.render_texture_with_matrix(texture, matrix, opacity)
        surface.send_frame_done(now)
Ejemplo n.º 2
0
 def get_box(self, reference: Output | None = None) -> Box:
     """
     Get the box of the layout for the given reference output in layout
     coordinates. If `reference` is None, the box will be for the extents of the
     entire layout.
     """
     if reference:
         box_ptr = lib.wlr_output_layout_get_box(self._ptr, reference._ptr)
     else:
         box_ptr = lib.wlr_output_layout_get_box(self._ptr, ffi.NULL)
     return Box(ptr=box_ptr)
Ejemplo n.º 3
0
    def get_geometry(self) -> Box:
        """Get the surface geometry

        This is either the geometry as set by the client, or defaulted to the
        bounds of the surface + the subsurfaces (as specified by the protocol).

        The x and y value can be <0
        """
        box_ptr = ffi.new("struct wlr_box *")
        lib.wlr_xdg_surface_get_geometry(self._ptr, box_ptr)
        return Box(box_ptr.x, box_ptr.y, box_ptr.width, box_ptr.height)
Ejemplo n.º 4
0
    def rectangles_as_boxes(self) -> list[Box]:
        nrects_ptr = ffi.new("int *")
        rects = lib.pixman_region32_rectangles(self._ptr, nrects_ptr)
        nrects = nrects_ptr[0]

        boxes = []
        for i in range(nrects):
            boxes.append(
                Box(rects.x1, rects.y1, rects.x2 - rects.x1, rects.y2 - rects.y1)
            )
            rects += 1
        return boxes
Ejemplo n.º 5
0
 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."""
     icon = dnd.wlr_drag.icon
     if icon.mapped:
         texture = icon.surface.get_texture()
         if texture:
             box = Box(
                 int((dnd.x - self.x) * scale),
                 int((dnd.y - self.y) * scale),
                 int(icon.surface.current.width * scale),
                 int(icon.surface.current.height * scale),
             )
             inverse = wlrOutput.transform_invert(icon.surface.current.transform)
             matrix = Matrix.project_box(box, inverse, 0, transform_matrix)
             self.renderer.render_texture_with_matrix(texture, matrix, 1)
             icon.surface.send_frame_done(now)
Ejemplo n.º 6
0
    def _on_frame(self, _listener, _data):
        wlr_output = self.wlr_output

        with PixmanRegion32() as damage:
            if not self._damage.attach_render(damage):
                # no new frame needed
                wlr_output.rollback()
                return

            with wlr_output:
                if not damage.not_empty():
                    # No damage, only buffer swap needed
                    return

                now = Timespec.get_monotonic_time()
                renderer = self.renderer
                renderer.begin(wlr_output._ptr.width, wlr_output._ptr.height)
                scale = wlr_output.scale

                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)
                    renderer.render_texture_with_matrix(
                        self.wallpaper, matrix, 1)
                else:
                    renderer.clear([0, 0, 0, 1])

                mapped = (self.layers[LayerShellV1Layer.BACKGROUND] +
                          self.layers[LayerShellV1Layer.BOTTOM] +
                          self.core.mapped_windows +
                          self.layers[LayerShellV1Layer.TOP] +
                          self.layers[LayerShellV1Layer.OVERLAY])

                for window in mapped:
                    if isinstance(window, Internal):
                        box = Box(
                            int((window.x - self.x) * scale),
                            int((window.y - self.y) * scale),
                            int(window.width * scale),
                            int(window.height * scale),
                        )
                        matrix = Matrix.project_box(
                            box, wlr_output.transform, 0,
                            wlr_output.transform_matrix)
                        renderer.render_texture_with_matrix(
                            window.texture, matrix, window.opacity)
                    else:
                        rdata = (
                            now,
                            window,
                            window.x -
                            self.x,  # layout coordinates -> output coordinates
                            window.y - self.y,
                            window.opacity,
                            wlr_output.scale,
                        )
                        window.surface.for_each_surface(
                            self._render_surface, rdata)

                if self.core.live_dnd:
                    self._render_dnd_icon(now)

                wlr_output.render_software_cursors(damage=damage)
                renderer.end()
Ejemplo n.º 7
0
    def _on_frame(self, _listener: Listener, _data: Any) -> None:
        with PixmanRegion32() as damage:
            try:
                if not self._damage.attach_render(damage):
                    # No new frame needed.
                    self.wlr_output.rollback()
                    return
            except RuntimeError:
                # Failed to attach render; skip.
                return

            with self.wlr_output as wlr_output:
                if not damage.not_empty():
                    # No damage, only buffer swap needed.
                    return

                now = Timespec.get_monotonic_time()
                scale = wlr_output.scale
                transform_matrix = wlr_output.transform_matrix

                with self.renderer.render(
                    wlr_output._ptr.width, wlr_output._ptr.height
                ) as renderer:

                    if self.wallpaper:
                        width, height = wlr_output.effective_resolution()
                        box = Box(0, 0, int(width * scale), int(height * scale))
                        matrix = Matrix.project_box(box, no_transform, 0, transform_matrix)
                        renderer.render_texture_with_matrix(self.wallpaper, matrix, 1)
                    else:
                        renderer.clear([0, 0, 0, 1])

                    mapped: Sequence[WindowType] = (
                        self.layers[LayerShellV1Layer.BACKGROUND]
                        + self.layers[LayerShellV1Layer.BOTTOM]
                        + self.core.mapped_windows  # type: ignore
                        + self.layers[LayerShellV1Layer.TOP]
                        + self.layers[LayerShellV1Layer.OVERLAY]
                    )

                    for window in mapped:
                        if isinstance(window, Internal):
                            box = Box(
                                int((window.x - self.x) * scale),
                                int((window.y - self.y) * scale),
                                int(window.width * scale),
                                int(window.height * scale),
                            )
                            matrix = Matrix.project_box(box, no_transform, 0, transform_matrix)
                            renderer.render_texture_with_matrix(
                                window.texture, matrix, window.opacity
                            )
                        else:
                            rdata = (
                                now,
                                window,
                                window.x - self.x,  # layout coordinates -> output coordinates
                                window.y - self.y,
                                window.opacity,
                                scale,
                                transform_matrix,
                            )
                            window.surface.for_each_surface(self._render_surface, rdata)

                    if self.core.live_dnd:
                        self._render_dnd_icon(self.core.live_dnd, now, scale, transform_matrix)

                    wlr_output.render_software_cursors(damage=damage)