Skip to content
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

Move windows with mouse #564

Closed
ISAKEM opened this issue Mar 28, 2024 · 12 comments · Fixed by #673
Closed

Move windows with mouse #564

ISAKEM opened this issue Mar 28, 2024 · 12 comments · Fixed by #673
Labels

Comments

@ISAKEM
Copy link

ISAKEM commented Mar 28, 2024

Is it possible to move windows between monitors with the mouse like u can do on FancyWM and Komorebi?

@LucaCoduriV
Copy link
Contributor

Looking for the same functionality :(

@LucaCoduriV
Copy link
Contributor

@HolbyFPV @lars-berger

Hi,

I'm currently exploring how to implement this feature. Although I have much to learn about the Windows API, I’m eager to contribute, especially because I would love to use this feature myself.

Here's a brief outline of how I envision implementing it:

  1. Detect when a window is being dragged.
  2. Capture the mouse position when the window drag state ends.
  3. Calculate the window's new position within the current workspace tree based on the mouse position.
  4. Move the window to the new position (handling the interaction with other windows is something I'm still figuring out).

As @HolbyFPV mentioned on Discord, some windows might not have a title bar. In such cases, we can combine a keyboard key with a mouse drag to move the window. Ultimately, the same approach should work for both scenarios.

I’ve looked at your platform code, and it seems we need to handle the WM_ENTERSIZEMOVE event to listen for both window drag and resize exits. (The resize part could be a separate issue, in my opinion).

I haven't delved much further into this yet because I want to ensure no one else is already working on it and to confirm that it’s okay for me to proceed.

Looking forward to your feedback!

@lars-berger
Copy link
Member

@LucaCoduriV Yeah absolutely, feel free to take a stab at it. The latest development branch is quick-test until the Rust rewrite gets merged.

There's a really cool POC that @Pamesta actually did a while back which might be a useful reference (demo video). Their branch is here.

There's different ways to approach the window move behavior and I'm not sure what's best. A couple things to consider:

  • Should it be possible to go from tiling -> floating when moving a window via drag? If so, when should this trigger?
  • Should the insert position be based off where the window is dragged to? e.g. insert at left/right depending on window position
  • Should it ever create a new split horizontally/vertically? e.g. create a vertical split if window is near the bottom of another window

IMO ideally we could have an implementation where it's just purely mouse click and drag, but if it really calls for it, it might be useful to have different behaviors if a specific key is held down.

@HolbyFPV
Copy link
Member

@LucaCoduriV it seems like you are on a good path 👍

@lars-berger brings up the tricky part of this implementation. If we had a way of previewing the placement before actually re-tiling, then we could easily support all of those bullet points. But without it, I'm afraid users would be unsure of what the behavior will be when the let go of their mouse. Maybe if we provided enough configuration settings we could make it work for enough people without any sort of preview.

The glaring issue with preview is that it would require including a UI library which GWM currently has none (thanks to Zebar). So I'm not sure how in scope this is.

If anyone reading has any .gifs of this feature in other WMs they want to mention here as inspiration, feel free!

@LucaCoduriV
Copy link
Contributor

LucaCoduriV commented Jul 23, 2024

@lars-berger Yep, I know that's an other reason why I want to help haha, I love rust.
Thanks for the POC I'll take a look for sure

Should it be possible to go from tiling -> floating when moving a window via drag?

I don't think that this feature is really interesting. Wouldn't it be easier to just press a key while hovering a window to make it floating or tiled ?

Should the insert position be based off where the window is dragged to? e.g. insert at left/right depending on window position
Should it ever create a new split horizontally/vertically? e.g. create a vertical split if window is near the bottom of another window

Based on Hyprland
It seems that they split vertically when the window width is bigger than the height and horizontally when the height is bigger than the width.
The position of the windows depends of where it was dropped on the other window

@lars-berger brings up the tricky part of this implementation. If we had a way of previewing the placement before actually re-tiling, then we could easily support all of those bullet points. But without it, I'm afraid users would be unsure of what the behavior will be when the let go of their mouse. Maybe if we provided enough configuration settings we could make it work for enough people without any sort of preview.

I am not sure if this is really important, I never had a preview while using this feature. It even might complicate things a lot because with a preview windows will move and we will need to find a way to not fall in a "recursive window moving every where" haha.

@LucaCoduriV
Copy link
Contributor

I am delving deeper into your code and have a few questions.

    // Snap window to its original position if it's the only window in the
    // workspace.
    if parent.is_workspace() && window.tiling_siblings().count() == 0 {
      state.pending_sync.containers_to_redraw.push(window.into());
      return Ok(());
    }

In this code you are looking for siblings, but I am not sure to understand what a sibling is.

My second question is about containers

pub enum Container {
  Root(RootContainer),
  Monitor(Monitor),
  Workspace(Workspace),
  Split(SplitContainer),
  TilingWindow(TilingWindow),
  NonTilingWindow(NonTilingWindow),
}

It seems each container type can have both a child and a parent, including RootContainer. Is this a possible scenario? If so, why? Also, is there a defined hierarchy? For instance, are workspaces always contained within monitors? If that's the case, why did you choose to use an enum instead of direct types?

Thank you for your answers; they will help me a lot. 😃

@lars-berger
Copy link
Member

Based on Hyprland
It seems that they split vertically when the window width is bigger than the height and horizontally when the height is bigger than the width.
The position of the windows depends of where it was dropped on the other window

That behavior sounds great 👍

In this code you are looking for siblings, but I am not sure to understand what a sibling is.

If a workspace has windows 1, 2, and 3, then window 2 + 3 are siblings of window 1. It’s the same with workspaces and monitors. The main state of the application is a tree where root -> monitors -> workspaces -> windows/split containers. The root is the only container that doesn’t have a parent. It’s represented as an enum because a) workspaces can have both windows + split containers as children b) some functions can return multiple container types (e.g. the focused container getter can either return a window or a workspace).

@LucaCoduriV
Copy link
Contributor

LucaCoduriV commented Jul 26, 2024

I've already made a draft pull request #635
It should be easier to track what I've done this way

I am not sure, but I think that it should be possible to link this issue to my PR.

@MisteryMonster
Copy link

Nice implement @LucaCoduriV ! I don't know currently tiling direction is determined by dragged position or have to manually change by hotkey alt + V (because I can accidentally move the window to a new horizontal split some time), I think it will be better to create vertical & horizontal split base on what position the window has been dragged to.

@LucaCoduriV
Copy link
Contributor

@MisteryMonster
HI, thank you. I totally agree with you. My implementation had the same behavior as the one from Hyprland. But just before releasing the v3, a bug was found making things less stable. To release something that is stable, most of my code was removed for now.

With @lars-berger, we are discussing to have something better than the behavior of Hyprland. But don't worry something better than now should come out (soon I hope).

@lars-berger
Copy link
Member

Closing this one in favor of #641

@LucaCoduriV's cooked up another pr which addresses issues with the current implementation, so should be landing soon 👍

Copy link

🎉 This issue has been resolved in version 3.2.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants