Skip to content

SWT Linux Gtk - Capturing screenshots broken in 4.35 #1891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
GregorQFS opened this issue Mar 10, 2025 · 7 comments · Fixed by #1893
Closed

SWT Linux Gtk - Capturing screenshots broken in 4.35 #1891

GregorQFS opened this issue Mar 10, 2025 · 7 comments · Fixed by #1893

Comments

@GregorQFS
Copy link

Describe the bug
Captured screen images on Linux don't change after the first capture. Regardless what happens on the desktop, the image remains constant.

To Reproduce

In essence I'm using the following code to capture the image.

public Image captureScreen(int x, int y, int width, int height)
{
Display display = Display.getCurrent();
Image swtImage = new Image (display, width, height);
GC gcDisplay = new GC (display);
gcDisplay.copyArea(swtImage, x, y);
}

Expected behavior

Call the method, do something to change the desktop, call the method again to get an updated screenshot

Screenshots

implicit

Environment:

  1. Select the platform(s) on which the behavior is seen:
    • All OS
    • Windows
    • Linux
    • macOS
  1. Additional OS info (e.g. OS version, Linux Desktop, etc)

Ubuntu 24.04, 22.04, 20.04

  1. JRE/JDK version

17.0.13

Version since
Eclipse or SWT version since when the behavior is seen
4.35

Workaround (or) Additional context
The bug was apparently introduced in the change to Image.java in revision 5c2611d

Reverting just the few lines in Image.java fixes the issue!

@iloveeclipse
Copy link
Member

What happens if you call dispose() on GC after use?

@ptziegler
Copy link
Contributor

What happens if you call dispose() on GC after use?

I can see the same behavior with Snippet 215 on my side as well.

@HeikoKlare
Copy link
Contributor

I can confirm the behavior with Snippet 215 on my system as well.

Side note: on a system using Wayland the functionality does not work at all, neither with the current nor with the previous state. It always produces a blank result.

Simplest solution would of course be to revert the change to Image in 5c2611d, which effectively reverts back to the old workaround (https://bugs.eclipse.org/bugs/show_bug.cgi?id=571166) that was supposed to be removed by that change.
Reverting that change would also render #1839 obsolete. However, it would mean that on GTK4 and systems running Wayland things will remain broken. I know that's a situation we have at several other places as well, but with more systems running Wayland, relying on such broken functionality will become less reasonable in the future.
Still, since at least I do not have the time to further investigate the issue and maybe find a solution without reverting the mentioned change, I would be fine with just doing the revert.

@ptziegler
Copy link
Contributor

However, it would mean that on GTK4 and systems running Wayland things will remain broken.

Just a remark: The copyArea() method isn't implemented on GTK4 when using a display-GC (the second else branch). So even if the Image class is adapted, this snippet still won't work.

void copyAreaInPixels(Image image, int x, int y) {
long cairo = Cairo.cairo_create(image.surface);
if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
Cairo.cairo_translate(cairo, -x, -y);
Cairo.cairo_push_group(cairo);
if (data.image != null) {
Cairo.cairo_set_source_surface(cairo, data.image.surface, 0, 0);
} else if (data.drawable != 0) {
if (!GTK.GTK4) GDK.gdk_cairo_set_source_window(cairo, data.drawable, 0, 0);
} else {
Cairo.cairo_destroy(cairo);
return;
}
Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE);
Cairo.cairo_paint(cairo);
Cairo.cairo_pop_group_to_source(cairo);
Cairo.cairo_paint(cairo);
Cairo.cairo_destroy(cairo);
}

I really don't see a conceptual problem with using cairo_image_surface_create over gdk_window_create_similar_surface, but I believe that the issue might be that one is returning an image surface, the other an xlib (at least on X11) surface.
To add to the confusion: This problem only seems to happen when capturing the display, but not e.g. a button.

Still, since at least I do not have the time to further investigate the issue and maybe find a solution without reverting the mentioned change, I would be fine with just doing the revert.

At least until someone can figure out what exactly is going on, that is probably the best solution. I'll still try to extend my test cases so that any future regression will be detected as early as possible.

@HeikoKlare
Copy link
Contributor

Just a remark: The copyArea() method isn't implemented on GTK4 when using a display-GC (the second else branch). So even if the Image class is adapted, this snippet still won't work.

Yes, thank you for the clarification. The whole functionality is not working on GTK4 or when using Wayland, no matter which version of the Image class is taken. I am not an expert in that area but since there are some other limitations on Wayland which, if I am not mistaken, have some security reasons (like positioning top-level shells), capturing the screen may be a functionality that is not allowed there anyway.

HeikoKlare added a commit to HeikoKlare/eclipse.platform.swt that referenced this issue Mar 10, 2025
…rm#1891

A previous change unified the Image surface initialization for blank
Image instances just based on height and width. Because of the change,
screen capturing using a GC on the display does only work properly when
executed the first time in an application lifecycle and in specific
situation, the initial properties of a GC changed (such as the text
anti-aliasing behavior). Due to a lack of a better solution for now,
this change reverts the unification of the Image surface initialization
to the previous state.

Fixes eclipse-platform#1891

This partially reverts commit 5c2611d.
@HeikoKlare
Copy link
Contributor

I've proposed the revert as:

If anyone has a better solution or would like to work on one, that would of course be highly appreciated and we can postpone merging the revert then.

@HeikoKlare
Copy link
Contributor

Since there was no idea for and no expression of interest for working on a different solution so far, I will merge the revert. Improving the behavior as a follow-up is of course still possible and will eventually be necessary for GTK4 anyway.

HeikoKlare added a commit to HeikoKlare/eclipse.platform.swt that referenced this issue Mar 12, 2025
…rm#1891

A previous change unified the Image surface initialization for blank
Image instances just based on height and width. Because of the change,
screen capturing using a GC on the display does only work properly when
executed the first time in an application lifecycle and in specific
situation, the initial properties of a GC changed (such as the text
anti-aliasing behavior). Due to a lack of a better solution for now,
this change reverts the unification of the Image surface initialization
to the previous state.

Fixes eclipse-platform#1891

This partially reverts commit 5c2611d.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants