winit icon indicating copy to clipboard operation
winit copied to clipboard

Can't resize window without decorations

Open CryZe opened this issue 5 years ago • 26 comments

When disabling decorations, the window can't be resized anymore, even with .with_resizable(true) specified. Maximizing and other operations don't seem to work either.

CryZe avatar Nov 22 '18 22:11 CryZe

Thanks for reporting this! I've successfully reproduced it.

This repo looks like a good exploration of how to fix this: https://github.com/melak47/BorderlessWindow

@Osspial, do you want to tackle this, or should I?

francesca64 avatar Nov 23 '18 23:11 francesca64

@francesca64 I'll look into this.

Osspial avatar Nov 25 '18 20:11 Osspial

It's not immediately clear what the best solution is for fixing this. The reason borderless windows can't be resized on Windows is that Windows, by default, shows resize handles on the window borders. The way melak47/BorderlessWindow works is that it reworks the resize detection code so that the resize handles appear inside the window's client area, and I'm not comfortable with automatically taking over an amount the edges of Winit windows to enable resize handles.

In the past, people have brought up having some sort of API for creating resize borders in the client area of borderless windows. @francesca64 What does the situation look like for resizing borderless windows on other platforms? If most/all of them have this behavior I think we should look into what API changes we'd need to support this.

If most other platforms do let you resize borderless windows, we could set it up so that you can drag on the window shadow to handle resizing. This is what Windows 10 does, but it's inconsistent with Windows 7 and may not work on Windows 7 machines with Aero disabled (since windows with that configuration don't have a window shadow).

Osspial avatar Nov 29 '18 01:11 Osspial

I think the best solution would be to implement this the same way it is done in Electron.

FrankenApps avatar Nov 15 '20 10:11 FrankenApps

I've tested this with X11 and Wayland in KDE and a window there is not resizable without decorations even when explicitly specifying with_resizable(true).

Cannot test in GNOME or other DEs sadly.

i509VCB avatar Apr 09 '21 03:04 i509VCB

I've tested this with X11 in GNOME Ubuntu, and it is not resizable either when with_decorations(false)

garasubo avatar Apr 09 '21 07:04 garasubo

I noticed this option in KDE, specifically in plasma settings, however enabling the option to add a handle to resize windows with no border does NOT change behavior from winit X11 or wayland.

Screenshot_20210514_165953

Uhh who would we ask here to change the labels on the issue so this is recognized as multi-platform?

i509VCB avatar May 14 '21 22:05 i509VCB

Uhh who would we ask here to change the labels on the issue so this is recognized as multi-platform?

:)

The people listed as either a maintainer or contributor in this table should usually be a good bet.

There are a couple of other issues on the issue tracker which are related to this issue, but which somehow haven't been linked: #221 (custom resize and dragging areas) and #1548 (aero snapping and maximization). I guess since #221 got closed, we can use this issue as the place to track custom resize areas.

maroider avatar May 14 '21 22:05 maroider

I have been looking into this myself, and it seems like APIs adjacent to the ones used to resolve #221 (in #1840) lend themselves well to solving this issue on anything but macOS. I've looked wherever I could, and I couldn't find a resizing analogue to performWindowDragWithEvent on NSWindow. What little I managed to find suggests that the "solution" is to manually adjust the position and size of the window, and that this will be performant enough that the resize operation will appear to be "native". I did find a SO answer that seems to lay out a different approach which somehow involves performWindowDragWithEvent, but I'm not entirely confident that this approach is one that will work. Neither SDL2 nor GLFW seem to support this on macOS, so there's little help to be found by looking at what APIs they use.

With this in mind, I think we can supply an API like Window::resize_window that works similarly to Window::drag_window with Wayland's wl_shell_surface::resize, X11's _NET_WM_MOVERESIZE_SIZE_*, and the WM_NCLBUTTONDOWN trick used in #1840 for Windows.

This still leaves us without a convenient API for defining a custom resize border, but such an API can later be built on top of Window::resize_window.

maroider avatar Jul 03 '21 20:07 maroider

I've spent a few hours getting my head around this for windows, and as far as dragging with the mouse is concerned I agree this can be solved very similarly to Window::drag_window. It's simply a matter of changing the Hit WPARAM to one of the resize options.

I tested this by changing winuser::HTCAPTION as WPARAM, to winuser::HTBOTTOMLEFT as WPARAM, in the drag window method for windows.

I'll try and find some time to implement a solution.

Edit:: I take it back, changing the code to winuser::HTBOTTOMLEFT as WPARAM, results in a failure with a borderless window but not with winuser::HTCAPTION as WPARAM, line 92 may have something to do with it: const NO_DECORATIONS_AND_MASK = !WindowFlags::RESIZABLE.bits; Though this could just be a shortcut for saying bitwise Not 1.

MrGibus avatar Aug 15 '21 16:08 MrGibus

Hi, what is the status on this? MacOS seems to support resize without decorations but Windows and Ubuntu don't.

Essentially need a window without title bar but with resizing.

Should this just be handled on client-side?

aniketbiprojit avatar Oct 07 '22 09:10 aniketbiprojit

I'm investigating this since it's necessary for Cosmic to implement client-side decorations in Iced.

mmstick avatar Oct 11 '22 17:10 mmstick

I have fully functioning support for X11 and Wayland. I'll submit a PR tomorrow. We can also automatically determine the direction of the resize based on pointer coordinates relative to the window, and the window size.

mmstick avatar Oct 11 '22 23:10 mmstick

Proof of functionality with a functioning libcosmic iced window.

https://user-images.githubusercontent.com/4143535/195220698-f07f94bc-8e62-4b55-a9d7-f0b882824f87.mp4

mmstick avatar Oct 12 '22 00:10 mmstick

That looks sort of wrong given that you have an orange border around the window and resize from the window surface instead of it.

On GNOME for example windows without decorations can be resized by holding Logo key, so cosmic can implement something like that as well.

I also don't understand the issue here, you clearly have decorations around the window?

kchibisov avatar Oct 12 '22 00:10 kchibisov

This isn't COSMIC but GNOME with pop-shell, and the orange border is the active hint border from the pop-shell extension. It's not a window decoration. Just a visual clue to show which window is actively focused.

mmstick avatar Oct 12 '22 00:10 mmstick

I don't think they are decorations. They feel like they have been put out manually as border as the cursor only turns inside the border.

I think the window should have a transparent area on all sides on hovering around which the cursor changes. I know that some windows capture that behaviour without drawing transparent areas but some just emit loose focus and don't track pointer outside the window (either glfw or sdl2 - don't remember which).

aniketbiprojit avatar Oct 12 '22 00:10 aniketbiprojit

Currently it feels like we need to be inside the border to re-size. So, anyhow not sure if this should be supported by winit or left to devs to come up with their own implementations if OS doesn't support out of the box.

aniketbiprojit avatar Oct 12 '22 00:10 aniketbiprojit

Without the active hint and a different background

Screenshot from 2022-10-12 02-44-17

mmstick avatar Oct 12 '22 00:10 mmstick

I think the window should have a transparent area on all sides on hovering around which the cursor changes.

So you basically want decorations but without title bar? Since the borders you're talking about are as well decorations. Some clients do shadows in them for example.

kchibisov avatar Oct 12 '22 01:10 kchibisov

So, anyhow not sure if this should be supported by winit or left to devs to come up with their own implementations if OS doesn't support out of the box.

This functionality is not possible to implement without winit, and I'd rather not have to maintain a fork of winit just to have window resize support for modern applications on Linux that use client-side decorations. X11 stops providing resize handles the moment you disable server-side decorations. Some Wayland implementations don't even support server-side decorations.

As mentioned before, the code to support it is virtually identical to drag_window. The drag_window method is how the HeaderBar widget in this demo is able to drag the window when clicked on. The window must decide where to place its resize handles rather than the display server with CSD. Very little code is required to expose the feature, and then I can create the resize handles in Iced similar to the headerbar.

mmstick avatar Oct 12 '22 01:10 mmstick

This functionality is not possible to implement without winit, and I'd rather not have to maintain a fork of winit just to have window resize support for modern applications on Linux that use client-side decorations

Having resize handles exposed is fine, I think there's even an issue/PR somewhere.

kchibisov avatar Oct 12 '22 01:10 kchibisov

You might be referring to https://github.com/rust-windowing/winit/pull/2003. This implements the functionality for Windows, but seems to have been abandoned now. I now have similar code functioning for Linux with both X11 and Wayland backends.

mmstick avatar Oct 12 '22 01:10 mmstick

You might be referring to https://github.com/rust-windowing/winit/pull/2003. This implements the functionality for Windows, but seems to have been abandoned now. I now have similar code functioning for Linux with both X11 and Wayland backends.

There's a lot of code smell around the PR and just the way in which borderless is currently done. My first preference is always to let the OS handle resize functionality along with super key support. Last I checked this may have had implications on the event loop. I need to find the time to really look into what needs to happen to get this functioning elegantly in windows.

I ended up veering away from winnit in favour of handling the windows myself.

In X11 my understanding is that the window manager handles decorations and getting away from reimplementing resizing is not possible. So something like the above PR would likely be needed.

MrGibus avatar Oct 12 '22 04:10 MrGibus

I think the main goal is Wayland here, since Wayland implies that you can handle decorations yourself.

kchibisov avatar Oct 12 '22 04:10 kchibisov

I will start with X11 support because Wayland requires changes to sctk (smithay-client-toolkit), and the next release of sctk will require some additional changes here to update to it.

mmstick avatar Oct 12 '22 10:10 mmstick