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

Respect win_gravity sizehint for floating windows #1335

Open
i3bot opened this issue Aug 2, 2014 · 13 comments
Open

Respect win_gravity sizehint for floating windows #1335

i3bot opened this issue Aug 2, 2014 · 13 comments
Assignees

Comments

@i3bot
Copy link

i3bot commented Aug 2, 2014

[Originally reported by lolilolicon@…]
(When a floating window with win_gravity sizehint set to CenterGravity and
XResizeWindow is called on it, i3 should keep the center of the window at
the here it is. Currently, i3 always keeps the NorthWest corner instead.
The documentation[1] talks about resizing a parent window, which makes
not sure if what I'm asking is a required behavior. BUT, I can confirm
that in Gnome, it works as I like it.

[1] http://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html#Gravity_Attributes

The window I'm talking about is set up with something like this:

XSizeHints sizehints;
sizehints.flags = PWinGravity;
sizehints.win_gravity = CenterGravity;
XSetWMNormalHints(dpy, win, &sizehints);

and later on change its size with

XResizeWindow(dpy, win, width, height);

Does this make sense to you? I'd like this because I added a that
CenterGravity bit to sxiv and a key binding to resize the window to fit
image size, and I don't want the perfectly centered window to change
positions after I press that key. Please consider this, thank you!

@stapelberg
Copy link
Member

I can see where you are coming from.

However, note that this is the first time in 5 years that someone actually makes use of the gravity feature, and i3 does not care about gravity at all in its entire code.

Personally, I’d say the gravity feature is old and crufty, and rarely-used.

Would it be possible for you to change your code to not rely on that? I think that’d make it compatible with a wide range of niche window managers.

@i3bot
Copy link
Author

i3bot commented Aug 8, 2014

[Original comment by lolilolicon@…]

Replying to comment 1 @…:

Would it be possible for you to change your code to not rely on that? I think that’d make it compatible with a wide range of niche window managers.

Yes, it seems possible to change my code to accommodate. But I have to change a simple XResizeWindow to first checking the sizehints myself with XGetWMNormalHints, followed by XGetGeometry, XTranslateCoordinates, and finally XMoveResizeWindow. It's not that much work, but it feels like a job more suitable for the window manager.

By default mpv (which also sets the win_gravity to CenterGravity) presents the same problem; fortunately, I was able to dig out the --force-window-position option. But then again, this feels like a lucky workaround.

Obviously, I won't always be able to find equivalent command line options, or to modify the source code, to make this work. That's why I really hope i3 will implement this support.

@i3bot
Copy link
Author

i3bot commented Aug 8, 2014

[Original comment by lolilolicon@…]

Replying to comment 2 by lolilolicon@…:

Replying to comment 1 @…:

Would it be possible for you to change your code to not rely on that? I think that’d make it compatible with a wide range of niche window managers.

Yes, it seems possible to change my code to accommodate. But I have to change a simple XResizeWindow to first checking the sizehints myself with XGetWMNormalHints, followed by XGetGeometry, XTranslateCoordinates, and finally XMoveResizeWindow. It's not that much work, but it feels like a job more suitable for the window manager.

Now as it turns out, for my code to work in both i3 and Gnome, I have to consider _NET_FRAME_EXTENTS too. Although the code seems to work, it's getting quite ugly, and I'm not quite sure why I need to plus/minus offsets differently depending on win_gravity in Gnome, all to cancel some offsetting done by Gnome's window manager...

@stapelberg
Copy link
Member

Replying to comment 2 by lolilolicon@…:

Replying to comment 1 @…:

Would it be possible for you to change your code to not rely on that? I think that’d make it compatible with a wide range of niche window managers.

Yes, it seems possible to change my code to accommodate. But I have to change a simple XResizeWindow to first checking the sizehints myself with XGetWMNormalHints, followed by XGetGeometry, XTranslateCoordinates, and finally XMoveResizeWindow. It's not that much work, but it feels like a job more suitable for the window manager.
Why do you need to check the size hints?

Also, wouldn’t you already know the current geometry? You get ConfigureNotify events for every size/position change, so you could keep track of that.

By default mpv (which also sets the win_gravity to CenterGravity) presents the same problem; fortunately, I was able to dig out the --force-window-position option. But then again, this feels like a lucky workaround.
Never noticed this. I do wonder why you’re using mpv as a floating window at all, though, given that i3 is a tiling window manager which an emphasized dislike of floating windows for anything except for password dialog popups :).

@i3bot
Copy link
Author

i3bot commented Aug 8, 2014

[Original comment by lolilolicon@…]

Replying to comment 4 @…:

Replying to comment 2 by lolilolicon@…:

Yes, it seems possible to change my code to accommodate. But I have to change a simple XResizeWindow to first checking the sizehints myself with XGetWMNormalHints, followed by XGetGeometry, XTranslateCoordinates, and finally XMoveResizeWindow. It's not that much work, but it feels like a job more suitable for the window manager.
Why do you need to check the size hints?

To get the value win_gravity hint. This is a custom command (that can be bound to a keybinding) for sxiv that resizes the window to the size of the displayed image.

Also, wouldn’t you already know the current geometry? You get ConfigureNotify events for every size/position change, so you could keep track of that.

Yes, sxiv stores the window geometry on ConfigureNotify. But I still need to call XTranslateCoordinates because sxiv does not keep track of this.

By default mpv (which also sets the win_gravity to CenterGravity) presents the same problem; fortunately, I was able to dig out the --force-window-position option. But then again, this feels like a lucky workaround.
Never noticed this. I do wonder why you’re using mpv as a floating window at all, though, given that i3 is a tiling window manager which an emphasized dislike of floating windows for anything except for password dialog popups :).

I've always floated media players since I started using tiling window managers, dwm, xmonad, awesome, etc. A tiled window forces a size different than the actual video size, and leaves black bars around the video; I really dislike that. Floating window for small videos, fullscreen for HD content, that's what I usually do.

What is particularly sticky is what I mentioned in comment 3. To have to offset for _NET_FRAME_EXTENTS really turns my code into something out of a window manager. I wonder what else could break this code now.


Now, I have some more test results on mpv and its --force-window-position option.

First, I have Alt+2 bound to set window-scale 0.5 in my mpv input.conf, which scales the mpv window to half the video size.

With --no-force-window-position: In Gnome, everything works; press Alt+2 and the window is scaled and kept in the center. In i3, since gravity is ignored, the window is scaled but not kept in the center.

With --force-window-position: In i3, everything works; press Alt+2 and the window is scaled and centered. In Gnome, when Alt+2 is pressed, the window is scaled, but not centered; every time Alt+2 is pressed, the window moves down 19 pixels; I recognize this bug, which only disappeared after I added the code to handle _NET_FRAME_EXTENTS in my own code.

Now consider that --no-force-window-position is the default behavior of mpv, and that is not without a good reason. It's best if the window manager can honor gravity hints and position the window as hinted, since it's one thing no application does better than the window manager.

@i3bot
Copy link
Author

i3bot commented Aug 8, 2014

[Original comment by lolilolicon@…]

Replying to comment 5 by lolilolicon@…:

With --force-window-position: In i3, everything works; press Alt+2 and the window is scaled and centered.

Actually, nope. I was writing this in Gnome, didn't really test it in i3. In i3, press Alt+2, the window is scaled, but not centered. And it also moves too, slightly. Looks like mpv is really managing its window very poorly in this case.

What --force-window-position does help in i3 is that it keeps the window at center when you switch to the next video in the playlist.

@stapelberg
Copy link
Member

Replying to comment 5 by lolilolicon@…:

Replying to comment 4 @…:

Replying to comment 2 by lolilolicon@…:

Yes, it seems possible to change my code to accommodate. But I have to change a simple XResizeWindow to first checking the sizehints myself with XGetWMNormalHints, followed by XGetGeometry, XTranslateCoordinates, and finally XMoveResizeWindow. It's not that much work, but it feels like a job more suitable for the window manager.
Why do you need to check the size hints?

To get the value win_gravity hint. This is a custom command (that can be bound to a keybinding) for sxiv that resizes the window to the size of the displayed image.
But why do you need to check the value of the gravity hint? Just never set it and assume it’s the default is what I’m proposing.

Also, wouldn’t you already know the current geometry? You get ConfigureNotify events for every size/position change, so you could keep track of that.

Yes, sxiv stores the window geometry on ConfigureNotify. But I still need to call XTranslateCoordinates because sxiv does not keep track of this.
Agreed.

What is particularly sticky is what I mentioned in comment 3. To have to offset for _NET_FRAME_EXTENTS really turns my code into something out of a window manager. I wonder what else could break this code now.
But you don’t have to account for the borders. The border width is handled by the window manager upon ConfigureRequests.

I still maintain that it should be doable in your application to implement resizing/moving in a relatively straight-forward fashion without jumping through too many hoops.

Take your time to do some tests and figure it out, maybe sleep a night over it. If you, after implementing the most straight-forward way to avoid the center gravity, still think it’d be better to have this code in the window manager, post your code and I’ll reconsider.

@i3bot
Copy link
Author

i3bot commented Aug 8, 2014

[Original comment by lolilolicon@…]

Replying to comment 7 @…:

Replying to comment 5 by lolilolicon@…:

Replying to comment 4 @…:

Why do you need to check the size hints?

To get the value win_gravity hint. This is a custom command (that can be bound to a keybinding) for sxiv that resizes the window to the size of the displayed image.
But why do you need to check the value of the gravity hint? Just never set it and assume it’s the default is what I’m proposing.

What is particularly sticky is what I mentioned in comment 3. To have to offset for _NET_FRAME_EXTENTS really turns my code into something out of a window manager. I wonder what else could break this code now.
But you don’t have to account for the borders. The border width is handled by the window manager upon ConfigureRequests.

There is a crucial difference between Gnome/mutter and i3 in handling XMoveResizeWindow(), which is all the reason why I had to add _NET_FRAME_EXTENTS handling in my code.

For example, say win is my application window, and its win_gravity is NorthWestGravity, now:

If I call XMoveResizeWindow(dpy, win, x, y, w, h) in i3, the top-left corner of win will be placed at (x, y); straight-forward.
If I call XMoveResizeWindow(dpy, win, x, y, w, h) in Gnome, the top-left corner of the win will be placed at (x + frame_left, y + frame_top); this is done so the top-left corner of the frame is placed at (x, y).

This behavior of Gnome forces me to get the frame extents via _NET_FRAME_EXTENTS, and calculate the x and y that are to be passed to XMoveResizeWindow() according to win_gravity.

One more example, if the win_gravity of win is CenterGravity, and the current absolute coordinates of win is (x, y) (which I get from either monitoring ConfigureNotify events or XGetGeometry()).
Now in order to ''keep win where it is'', what should I pass to XMoveResizeWindow()? The answer is XMoveResizeWindow(dpy, win, x + (frame_right - frame_left)/2, y + (frame_bottom - frame_top)/2, w, h).
Maybe I should explain how I reached that value, say x_passed is the X coordinate passed to XMoveResizeWindow(), since the win_gravity is CenterGravity, Gnome/mutter will keep the coordinates of the center of win and later of the window frame at the same position. So we have:

x_center == x_passed + w/2 == (x - frame_left) + (frame_left + w + frame_right)/2
y_center == y_passed + h/2 == (y - frame_top) + (frame_top + h + frame_bottom)/2

And this turned out to work in Gnome/mutter.

I still maintain that it should be doable in your application to implement resizing/moving in a relatively straight-forward fashion without jumping through too many hoops.

Unless there is either a straight-forward way to get the correct coordinates to pass to XMoveResizeWindow(), or a better alternative to XMoveResizeWindow(), I can't find a more straight-forward way to satisfy both i3 and Gnome.

Take your time to do some tests and figure it out, maybe sleep a night over it. If you, after implementing the most straight-forward way to avoid the center gravity, still think it’d be better to have this code in the window manager, post your code and I’ll reconsider.

If the above turns out to be not clear or convincing enough, I will prepare a patch for sxiv so you can test it out.

Note that my code used to be a simple XResizeWindow(dpy, win, w, h) and the window positioning was handled automatically by Gnome according to win_gravity. If i3 did the same, I wouldn't have to go so far as to get to know stuff like _NET_FRAME_EXTENTS...

@i3bot
Copy link
Author

i3bot commented Aug 9, 2014

[Original comment by lolilolicon@…]

sxiv patch v1 http://ix.io/dOu
sxiv patch v2 http://ix.io/dOv

To test, see the note at the header of the files.

@i3bot
Copy link
Author

i3bot commented Aug 10, 2014

[Original comment by lolilolicon@…]

I added some logic in my code to check _NET_SUPPORTED for _NET_FRAME_EXTENTS support so it works more reliably.

Speaking of which, shouldn't i3 support _NET_FRAME_EXTENTS though? The EWMH spec states,

The Window Manager MUST set _NET_FRAME_EXTENTS to the extents of the window's frame.
I understand that this doesn't make much sense for tiled windows, but for floating windows it's kind of useful.

In any case, I wonder, is the application supposed to check and adapt in order to place its window where it wants? Now, if I want my application to work in as many window managers as possible, I probably have to do such things. But should i3 be one of those broken window managers that require such work on the application's part?

I will again quote the EWMH spec,

Window Managers MUST honor the win_gravity field of WM_NORMAL_HINTS for both MapRequest and ConfigureRequest events (ICCCM Version 2.0, §4.1.2.3 and §4.1.5)

Would it require too much effort to implement this?

@stapelberg
Copy link
Member

I think the basic problem is #1341, i.e. the “does-the-frame-count” question that seems to be handled differently in i3 than in other window managers.

Once that is fixed, I don’t think we need to bother with geometries.

That said, not sure when/if I’ll get around to looking into these (tedious) issues. Patches appreciated at http://cr.i3wm.org/

@i3bot
Copy link
Author

i3bot commented Aug 10, 2014

[Original comment by lolilolicon@…]

Well, I took a look at src/handlers.c, the handle_configure_request() function is likely where work is needed to fix this. I haven't run this in debug mode to confirm, but by the looks of it, a simple XResizeWindow() would not make i3 do anything about the x y coordinates, which is where the problem lies. I don't think it'd be hard to add gravity logic here, but I don't know the structure of the codebase at all so I will not attempt it myself.

#1341 is related, but not that much. I think gravity handling can be fixed by itself, without considering the frame irregularity.

@i3bot
Copy link
Author

i3bot commented Aug 27, 2014

[Original comment by lolilolicon@…]

Replying to comment 8 by lolilolicon@…:

Note that my code used to be a simple XResizeWindow(dpy, win, w, h) and the window positioning was handled automatically by Gnome according to win_gravity. If i3 did the same, I wouldn't have to go so far as to get to know stuff like _NET_FRAME_EXTENTS...

For reference, adding this quote from the EWMH spec,

If an Application requests just a new size, its reference point does not move. So for example if client window has win_gravity SouthEastGravity and is resized, the bottom right corner of its frame will not move but instead the top left corner will be adjusted by the difference in size.

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

No branches or pull requests

3 participants