wails icon indicating copy to clipboard operation
wails copied to clipboard

Window maximum width and height issues on Linux Wayland

Open spinzed opened this issue 1 year ago • 7 comments

Description

There are 3 similar issues that I've found:

  1. It is not possible to resize window beyond a certain width and height for some reason (although MaxWidth and MaxHeight are unset).
  2. Maximizing the window will move the window to the top left of the screen but it won't take up the entire screen (similarly to the first bug).
  3. When making the window fullscreen, the window itself will go fullscreen but the webview inside it won't and will center itself in the window.

To Reproduce

For all:

  1. Make sure you are on Wayland and the app is not ran under Xwayland.
  2. Unset MaxWidth and MaxHeight or set them to a high value (close to the screen width and height)
  3. Launch app

First bug:

  • Try to resize manually and make the window as big as possible. Second bug:
  • Click maximize. Third bug:
  • Fullscreen the app.

Expected behaviour

First bug: The app resizes accordingly without constraints. Second bug: The app maximizes. Third bug: The app goes to fullscreen.

Screenshots

Screencast from 2023-02-28 14-06-22.webm

Attempted Fixes

No response

System Details

# System

OS           | Manjaro Linux
Version      | Unknown      
ID           | manjaro      
Go Version   | go1.19.4     
Platform     | linux        
Architecture | amd64        

# Wails

Version         | v2.3.1
Package Manager | pacman

# Dependencies

Dependency | Package Name | Status    | Version    
*docker    | docker       | Available | 1:23.0.1-1 
gcc        | gcc          | Installed | 12.2.1-2   
libgtk-3   | gtk3         | Installed | 1:3.24.36-1
libwebkit  | webkit2gtk   | Installed | 2.38.5-1   
npm        | npm          | Installed | 8.19.2-1   
pkg-config | pkgconf      | Installed | 1.8.0-1    
* - Optional Dependency

Additional context

I have tried to reproduce the problem under Xwayland (launching the app with GDK_BACKEND=x11 and XDG_SESSION_TYPE=X11) but the bugs weren't present there.

I also successfully managed to reproduce the bugs on another machine running Arch with Gnome on Wayland.

Strangely, it also seems that the "phantom maximum width and height" depend on the GTK theme - for some themes they are a bit bigger and for some they are a bit smaller.

spinzed avatar Feb 28 '23 13:02 spinzed

Sounds like an upstream bug. Maybe @Lyimmi or @tmclane have more knowledge

leaanthony avatar Feb 28 '23 19:02 leaanthony

Sounds wonderful, I'll take a look at it as soon as I have time this week. (I hope)

lyimmi avatar Feb 28 '23 21:02 lyimmi

Hi, sorry it took me so long to look into this. I think I found the core of the issue.

Wails sets default min and max sizes for the window when they are not set in the app options (to the current display's resolution) and we pass the window geometry hints GDK_HINT_MAX_SIZE | GDK_HINT_MIN_SIZE to GTK as well, so GTK tries to respect the set window dimension limits.

If I remove the hints in v2/internal/frontend/desktop/linux/window.c L:190 the problem goes away, but then we have no built in window size control via GTK.

As far as I can tell the default Wayland compositor counts the shadows/borders/etc in the window's width and height.

For a quick and dirty temporary fix I recommend to set the window max values in the app options to some arbitrary big number (maybe over a 4k displays resolution).

I'll look into how fix this properly. By the way this is not a unique Wails problem, I found lots of other issues about this, including electron.

lyimmi avatar Mar 31 '23 11:03 lyimmi

Thanks for looking into this @Lyimmi 🙏

leaanthony avatar Mar 31 '23 11:03 leaanthony

Thank you for checking this out! I've tried to look into this myself, but I am far too unfamiliar with GTK to do anything here, especially when taking into account those Wayland quirks.

Nevertheless, I'm grateful for your efforts and I'll provide you with any additional info if I find any. Cheers!

spinzed avatar Mar 31 '23 19:03 spinzed

FWIW, I experience the same issue. Installed wails today, ran the sample app and then just hit "toggle maximize" key combo on the window, it only gets it partially maximized (top+left, leaving a gap on bottom+right).

Wails doctor
# Wails
Version         | v2.7.1
Package Manager | dnf   

# System
┌────────────────────────────────────────────────────────────────────────────────┐
| OS           | Fedora Linux                                                    |
| Version      | 39                                                              |
| ID           | fedora                                                          |
| Go Version   | go1.21.6                                                        |
| Platform     | linux                                                           |
| Architecture | amd64                                                           |
| CPU          | Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz                       |
| GPU 1        | GM107M [GeForce GTX 960M] (NVIDIA Corporation) - Driver: nvidia |
| GPU 2        | HD Graphics 530 (Intel Corporation) - Driver: i915              |
| Memory       | 15GB                                                            |
└────────────────────────────────────────────────────────────────────────────────┘

# Dependencies
┌────────────────────────────────────────────────────────┐
| Dependency | Package Name        | Status    | Version |
| *docker    | moby-engine         | Installed | 24.0.5  |
| gcc        | gcc-c++             | Installed | 13.2.1  |
| libgtk-3   | gtk3-devel          | Installed | 3.24.41 |
| libwebkit  | webkit2gtk4.0-devel | Installed | 2.42.3  |
| npm        | nodejs-npm          | Installed | 10.2.3  |
| pkg-config | pkgconf-pkg-config  | Installed | 1.9.5   |
| *upx       | upx                 | Installed | 4.2.2   |
└─────────────── * - Optional Dependency ────────────────┘

Screencast from 2024-02-06 12-11-13.webm

I use Gnome 45.3 on Wayland.

alexaandru avatar Feb 06 '24 10:02 alexaandru

I think I found a way to fix this issue, but I have not seen this kind of solution anywhere, so I'm not exactly sure if it is a good solution.

Basically we could compare the window's initial size and the allocated size that contains the window decorators and shadows as well and add the difference to the window's max size values.

The comparison can be ignored on frameless windows because non decorated windows report the correct size on Wayland.

As far as I can tell the initial window size does not mater, the size of the decorators does not change just the window's size.

The solution still behaves badly on my portrait display, because for some reason Wayland returns the main display's resolution... So the max height is about half of the portrait display's height. At this time I can't figure out why.

What do you think @leaanthony, is it good enough for a PR?

Edit: it needs more work, maximising works, but fullscreen and unfullscreen is still broken.

It would look like this:


void SetMinMaxSize(GtkWindow *window, int min_width, int min_height, int max_width, int max_height)
{
    GdkGeometry size;
    size.min_width = size.min_height = size.max_width = size.max_height = 0;

    GdkRectangle monitorSize = getCurrentMonitorGeometry(window);
    if (isNULLRectangle(monitorSize))
    {
        return;
    }
    int flags = GDK_HINT_MAX_SIZE | GDK_HINT_MIN_SIZE;
    size.max_height = (max_height == 0 ? monitorSize.height : max_height);
    size.max_width = (max_width == 0 ? monitorSize.width : max_width);
    size.min_height = min_height;
    size.min_width = min_width;

// wayland specific code start
# ifdef GDK_WINDOWING_WAYLAND
    char *gdkBackend = getenv("XDG_SESSION_TYPE");
    if (gdkBackend != NULL && strcmp(gdkBackend, "wayland") == 0 && gtk_window_get_decorated(window)) {
        int windowWidth, windowHeight;
        gtk_window_get_size(window, &windowWidth, &windowHeight);

        GtkAllocation windowAllocation;
        gtk_widget_get_allocation(GTK_WIDGET(window), &windowAllocation);

        // only for debug
        g_printf("window decorated: %d\n", gtk_window_get_decorated(window));
        g_printf("window alloc width:%d height:%d\n", windowAllocation.width, windowAllocation.height);
        g_printf("window window width:%d height:%d\n", windowWidth, windowHeight);
        g_printf("window & decorator diff width:%d height:%d\n", (windowAllocation.width-windowWidth), (windowAllocation.height-windowHeight));
        g_printf("window max width:%d height:%d\n", size.max_width, size.max_height);

        size.max_height = (windowAllocation.height-windowHeight)+size.max_height;
        size.max_width = (windowAllocation.width-windowWidth)+size.max_width;

        // only for debug
        g_printf("window new max width:%d height:%d\n", size.max_width, size.max_height);
    }
#endif
// wayland specific code end

    gtk_window_set_geometry_hints(window, NULL, &size, flags);
}

It prints:

window decorated: 1
window alloc width:1452 height:857
window window width:1400 height:768
window & decorator diff width:52 height:89
window max width:2560 height:1080
window new max width:2612 height:1169

lyimmi avatar Feb 07 '24 21:02 lyimmi