How to see if a window is minimised in GTK4 on Wayland


I was wondering how to check if a window is minimised/visible on screen (so I can stop rendering and not have so much performance impact if the results aren’t even visible).

I’ve looked at the docs which say to check minimisation state using the GdkToplevel::state property.
(As a side note, it is difficult to see how to get this - there does not seem to be a function to get the GdkToplevel from a GtkWindow and it is not highlighted anywhere that the way to do this seems to be to get the GdkSurface from the GtkNative interface and then use GDK_TOPLEVEL to case that to a GdkToplevel, before finally getting the state.)

I have tried this, but on Wayland, the GDK_TOPLEVEL_STATE_MINIMIZED bit is never set. On X, it works fine, but I’d like this to work on Wayland too.

Am I doing this wrong? Is there another, better way to check if a window is minimised, which would work on Wayland too?

P.S. I know Wayland can be restrictive in terms of windowing information for security reasons but I know GLFW manages to provide this information and it’s relevant and local to the window anyway - basically I know there are ways to get it for Wayland windows, but it’d be nice to use GTK’s cross-platform interface, and I was wondering how to do that.

1 Like

No, there is no “minimized” state in Wayland, mostly because Wayland compositors are entitled to handle what “minimized” means. For instance, even if you minimize a window under GNOME Shell, the compositor is will keep showing it in the overview, which means the window is still expected to update itself. Other compositors might not implement minimization at all: you’re just asking to minimize the window, nothing else.

See the discussion in the GTK issue tracker, and the implementation of the “minimize” method.

Ah, ok. Sorry for my mistake.

I think I see now that it’s a bit more complex…
I looked in the wayland docs (XDG shell protocol | Wayland Explorer) which say:

“If you are looking to throttle redrawing when minimized, please instead use the wl_surface.frame event for this, as this will also work with live previews on windows in Alt-Tab, Expose or similar compositor features.”

This sounds like what I’d like to do - prevent excessive recalculation when the window is completely hidden.
I looked at GTK to see how I could use this idea, and it seems there are frame events / "render" signals associated with GdkSurface. (I tried to use this but the signal never seemed to fire?)

Am I going about this the right way at all? What is the proper way in GTK to utilise this functionality? I’m hoping for some kind of event I can bind to which will fire at the screen’s refresh rate when the window is being drawn/is visible - does such an event exist?

(Maybe I’m asking the wrong questions - if so, I’m sorry. I’m building a system monitor and I want to stop wasting CPU cycles on monitoring the system if the results aren’t going to be displayed due to the window being hidden.)

Many thanks for your time!

You cannot handle the frame events directly from GTK: they are requests made by the toolkit, not to the toolkit. The Wayland book is meant as an introduction on how to write a Wayland client from a toolkit perspective.

You can theoretically call gdk_wayland_surface_get_wl_surface() and attach a frame callback with wl_surface_frame(), but you would not be allowed to change the state of your UI and cause a redraw from there, as you’d be messing around with GTK’s own internal state.

In practice, Wayland has no real mechanism to let you throttle your rendering in case a surface is minimised because in most known cases, “minimised” does not really mean “invisible” like “iconified” used to mean in (uncompositoed) X11.

Just to add to the above, this to me was a key difference between Wayland and X11. A Wayland compositor expects to be able to redisplay a hidden window immediately, for example in gnome-shell when opening the overview. It’s not like X11 where the server sends MapRequest and then waits. The only way to ensure there is never any delay and the user never sees a stale frame is to always keep the window updated. So while surface frame events may work in some capacity, they are probably not what is wanted anyway.

If you really must hack surface events in, then you probably want to do something like setting a timeout of a few seconds after the most recent frame event and fading out to a “GUI inactive” state when it triggers. Then when you start getting frame events again you fade back in. This is similar to what gnome-shell already does when transitioning to/from a maximize state and ensures the user never sees a “jump” from a stale frame to a more recent one.

Thank you both for your replies…

I have tried @ebassi’s suggestion of using wl_surface_frame(), and I have managed to get the callbacks working… Unfortunately, they’re not particularly useful to me, since

  • They only fire when the surface is committed, which for GTK seems to be when the window is resized or hidden/shown - so the frequency of callbacks is much less than the rendering framerate of my program. In fact, the thing which causes it to fire most of the time is my own program periodically updating its internal widgets.
  • The callbacks continue even when the program is completely hidden - so I cannot see any way to tell whether the program is being displayed based on the time since last callback.

Basically, the time since last callback is always <1s since my program updates its state every 1s, and this seems to trigger a wayland callback even when the program isn’t shown at all.

Are there any other mechanisms I could use to tell when GTK is actually showing new frames/sending new requests, or just overall to see if there is any point in updating my UI with new data?

Thanks again for taking the time…

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.