Skip to content

Commit

Permalink
Use a direct rendering approach for GTK screenshots.
Browse files Browse the repository at this point in the history
  • Loading branch information
freakboy3742 committed Oct 27, 2023
1 parent de64eac commit 54e5e31
Showing 1 changed file with 22 additions and 35 deletions.
57 changes: 22 additions & 35 deletions gtk/src/toga_gtk/window.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import os
from io import BytesIO

from toga.command import GROUP_BREAK, SECTION_BREAK
from toga.handlers import wrapped_handler

from .container import TogaContainer
from .libs import Gdk, Gtk
from .libs import Gtk, cairo


class Window:
Expand Down Expand Up @@ -154,36 +154,23 @@ def set_full_screen(self, is_full_screen):
self.native.unfullscreen()

def get_image_data(self):
if os.environ.get("XDG_SESSION_TYPE", "").lower() == "x11":
display = self.native.get_display()
display.flush()

# For some reason, converting the *window* to a pixbuf fails. But if
# you extract a *part* of the overall screen, that works. So - work
# out the origin of the window, then the allocation for the
# container relative to that window, and capture that rectangle.
window = self.native.get_window()
origin = window.get_origin()
allocation = self.container.get_allocation()

screen = display.get_default_screen()
root_window = screen.get_root_window()
screenshot = Gdk.pixbuf_get_from_window(
root_window,
origin.x + allocation.x,
origin.y + allocation.y,
allocation.width,
allocation.height,
)

success, buffer = screenshot.save_to_bufferv("png")
if success:
return buffer
else: # pragma: nocover
# This shouldn't ever happen, and it's difficult to manufacture
# in test conditions
raise ValueError(f"Unable to generate screenshot of {self}")
else: # pragma: no-cover
# Wayland requires a different API. We also don't (can't?) run CI
# under Wayland, so mark this branch no-cover.
raise NotImplementedError("Cannot take screenshots under Wayland.")
display = self.native.get_display()
display.flush()

width = self.container.get_allocation().width
height = self.container.get_allocation().height

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
context = cairo.Context(surface)

# Render the background of the window into the Cairo context
Gtk.render_background(
self.native.get_style_context(), context, 0, 0, width, height
)

# Render the content of the window.
self.container.draw(context)

data = BytesIO()
surface.write_to_png(data)
return data.getbuffer()

0 comments on commit 54e5e31

Please sign in to comment.