Using GLFW under Wayland

Hi,

I am using GLFW to do Vulkan rendering, and I was wondering if using Wayland is possible with GLFW actually.

I am using GLFW 3.3.2 (provided by an Ubuntu package).

Actually opening a window (I am using Gnome Shell), will provide a plain white decoration around the window.

If I choose to use this decoration here are the problems :

  • If content scaling is activated on the desktop, the decorations seem to be scaled but the window itself is not. So for a 2x2 scaling the window will use a quarter of the area.
  • Furthermore if one use fractional scaling, the scale reported by glfwGetMonitorScale() will only be integers (is this a problem with Gnome Shell or with GLFW though ?)
  • I don’t see any way to draw inside these white decorations myself or to choose their size or to modify their behavior ?

If I choose to remove decorations (window hint GLFW_DECORATED set to false) and decide do “simulate” decorations myself, here are the problems :

  • I cannot position the window using glfwSetWindowPos() so my window will always appear around the top-left corner of the screen and will not be allowed to move by any way.

So I am a bit stuck with all this. Do I do something wrong ? Should I try directly the GLFW sources ? My test program is simple :

glfwInit();
GLFWwindow* window = glfwCreateWindow(256, 256, "test", NULL, NULL);
glfwSetWindowPos(window, 256, 256);
glfwShowWindow(window);
while (true) {
    glfwPollEvents();
}

I am willing to help if necessary for testing or any other way to make this work.

Thanks a lot for any advice and help. By the way GLFW is a great library !

P.S. why I don’t want to use the X11 version : well, I am using Wayland and Gnome Shell that I like both a lot :wink: Furthermore Wayland seems to be the future. And finally when using the X11 version the scaling is also bad but this time no way to avoid having a blurry upscaled window.

GLFW has Wayland support as per the second line of the readme on Github.

  1. I’m not sure what the behaviour for Wayland is with content scaling but it’s likely that pixels map 1:1 to screen coordinates, so you may want to use GLFW_SCALE_TO_MONITOR, see the documentation on window content scale.
  2. I’m unsure what the behaviour of glfwGetMonitorContentScale should be on Wayland. The integer scaling may be correct.
  3. You cannot draw into the window decorated area, but you can potentially set the window title text and window icon. Note that on Wayland the remarks in the documentation state that the icon cannot be changed. One way around this is to not use a decorated window and then draw your own window decorations.
  4. You cannot set a windows position on Wayland, see remarks in the glfwSetWindowPos documentation.

Thank a lot for you for your fast answer :slight_smile:

GLFW has Wayland support as per the second line of the readme.

Yes, I read that, sorry if my question seemed naive. I use XWayland (GLFW not compiled with Wayland support) since 6 months or so, but it is frustrating not to be able to use Wayland backend. And I am super happy with GLFW excepted for the problems I listed above :slight_smile:

  1. I’m not sure what the behaviour for Wayland is with content scaling but it’s likely that pixels map 1:1 to screen coordinates, so you may want to use GLFW_SCALE_TO_MONITOR

I tried GLFW_SCALE_TO_MONITOR. Using it or not if I ask a window of 256x256 pixels I get a window of 192x192 pixels (with scaling 1.5 on, same kind of errors if scaling is 2).

If I ask window decorations, I still get the same window size but with decorations that are twice this size. It seems, this behaviour happens as soon as scaling is not 1x1.

Capture d’écran de 2020-04-24 12-28-41

In fact I am willing to avoid using scaling at all, I would like to provide exact pixel sizes. But GLFW does use some scaling information somewhere, and I don’t know how to specify the size of my window without GLFW applying some scaling on the values I give. Furthermore I cannot get the correct scale values from glfwGetMonitorScale() to do the maths myself.

  1. I’m unsure what the behaviour of glfwGetMonitorContentScale should be on Wayland. The integer scaling may be correct.

I won’t argue on this, this could be a design decision. But this prevent users to have their screen in such configurations.

In any case if my screen is at 1.5 scale, with XWayland glfwGetScreenScale() gives me 1x1 and with Wayland I get 2x2.

  1. You cannot draw into the window decorated area, but you can potentially set the window title text and window icon. Note that on Wayland the remarks in the documentation state that the icon cannot be changed. One way around this is to not use a decorated window and then draw your own window decorations.

I am willing to draw my own decoration if needed… but in that case, as I cannot change the window position, it becomes unusable. No user of my application will want to be stuck with a window that can’t be moved by dragging its title bar, and I would have to simulate this behaviour.

  1. You cannot set a windows position on Wayland, see remarks in the glfwSetWindowPos documentation.

Yes I discovered that after posting, sorry. Therefore this forces us to use decorated windows with the size problem listed above. With all due respect, I cannot imagine that the white large blank borders are here to stay ?

Some of the limitations are explicit to Wayland, not GLFW. For example the integer scaling is due to Waylands protocol providing only an integer scaling output, and Wayland doesn’t permit window positioning.

Looking at the code, GLFW_SCALE_TO_MONITOR does not appear to be used by the GLFW Wayland - the documentation does state that This hint only has an effect on platforms where screen coordinates and pixels always map 1:1 such as Windows and X11.

It would be interesting to see what glfwGetWindowContentScale returns for your window - looking at the code it appears to select the highest scale on any monitor attached, which is not what I would expect, however this is due to a limitation of Wayland as we can’t tell where the window is.

GLFW respects this window scale during re-sizing:

Overall most of the limitations appear to be due to the design of Wayland combined with GLFW being cross platform. An alternative Wayland only API might be able to handle things better, but Wayland’s idiosyncrasies make this hard. I imagine things will improve over time as both Wayland and GLFW evolve, but it’s possible some issues may never be resolved.

Yes, you’re asbsolutly right.

I was looking at all this on my side. Due to this wayland limitation to integer scales, Gnome Shell supports fractional scaling using a trick : if the scale is say 1.5, they tell the client the scale is 2 (wich is indeed what we obtain from getScreenContentScale) and then downsizes the content.

The window is 1.5 x the size in pixels, but the buffer where the application draws is 2 x the size. The results look sharp.

Sadly when using XWayland it does the reverse : it says scale 1 and upscales the buffers. This produces blurry results.

It would be interesting to see what glfwGetWindowContentScale returns for your window - looking at the code it appears to select the highest scale on any monitor attached, which is not what I would expect, however this is due to a limitation of Wayland as we can’t tell where the window is.

On my installation it returns 1 for the window content scale (2 for the screen). Which is for the best because Wayland does a scaling of the values we send it (I think they work in “logical” pixels instead of real ones, am I right ?).

Indeed, and I know how difficult it is to provide an API that covers so many different platforms.

However I still have bugs with the size of windows even when running the tests from the GLFW git repository directly. I think they are related to my Gnome Shell environment, but unsure.

I tested with triangle-vulkan.c, and ensured I was building GLFW for Wayland. When creating the window, simply clicking in another window and then back in the triangle app, will make it larger and larger as I click. It starts as a square and tends to become taller. Therefore I was thinking this is due to the decoration sizes being mistakenly used during resize (since the decorations are taller on top). The demo program does not use a mouse callback so it is not an expected behavior.

Trying to resize the window from the sides will also produce strange results : the window will resize in all directions but sometimes enlarging in one direction, say X, and shrinking in the other, Y.

Anyway thank you for your answers and time. Much appreciated !

It’s possible that these issues are related to Gnome Shell with Wayland - there’s already another related issue posted:

I think it’s worth posting the odd resizing issue, especially if you can reproduce on the simpler triangle-opengl.c example.

Thank you, I’ll do that.