Closed aacebedo closed 4 years ago
The ewmh package is just a dumb convenience layer for interacting with a window manager using the ewmh spec. In order to understand the package, you need to understand the spec. The spec explains the difference between moveresize and wmmoveresize for example.
As for your problem, you'll need to investigate the wm. Xgbutil is just sending a message. The wm is what implements the moveresize itself.
You should consider that some windows (most commonly terminals) are only allowed to be certain widths or heights based on an interval of fixed increments chosen by the client, usually related to font size. You haven't really given enough details to tell whether that's the case here. In any case, the WM enforces that too IIRC.
In the end, moveresize is just a request. The wm decides what to do. So that's what you need to investigate next. You could try other tools, like wmctrl, to make sure there is nothing funny happening in xgbutil or if there is some better technique. But I doubt it.
You might also consider using: https://godoc.org/github.com/BurntSushi/xgbutil/xwindow#Window.WMMoveResize
Again, see package docs for the difference between moveresize and wmmoveresize.
See also: https://godoc.org/github.com/BurntSushi/xgbutil/xwindow#Window.DecorGeometry
Apparently there is some additional complexity here with respect to window decorations. This is what xwindow.WMMoveResize tries to account for I think.
Thank you for this fast reponse !
I am quite a newbie with everything about X development. I'll take a closer look to the links you've provided. Yes I am manipulating a terminal window. I struggle to understand exactly the relation between (X and the WM (I guess i3 for me ?)).
I modified my code to use directly xgb instead of xgbutil and use the ConfigureWindowChecked as I thought it was closer to the X server. I noticed that if I poll the window geometry (with RawGeometry) it changes itself automatically after 3 ou 4 ms (from the wrong to the correct reported value). It still doesn't solve my problem but it explains the change of the geometry between two consecutive runs.
wmctrl has the same behaviour. First run incorrect size, second run correct. The width increment (8) is a divider of the requested width (640).
Yeah then this isn't a problem with xgbutil. If you're new to X, then you'll want to read and understand icccm and ewmh. Otherwise, ask the i3 folks for help. But try xwindow.wmmoveresize.
Otherwise, it has been many many years since I've done anything X related. The history of this project should be informative. Sorry I can't be of more help.
:( Thank I'll continue to search. i3 folks told me to go and check xcb... :) That's the reason I was here. I have updated the issue on their side to continue my research
Aye. I think the fact that both xgbutil and wmctrl behave the same means it's probably on the WM side. Remember, all xgbutil is doing here is sending a client message. xwindow.WmMoveresize
is a little bit smarter in that it tries to take window decorations into account. But that's it.
I'd also like to say that i3 may well be behaving as expected here. Window geometry and resizing in the X world is a strange beast. I remember being confounded by it several times. I recall being stymied by it when I wrote pytyle, which was a tiling tool that sat on top of window managers. It was often the case that pytyle simply could not resize windows to a precise geometry, and you just had to be okay with small gaps.
Also, using wmctrl
to show your problem may have better results than using xgbutil. xgbutil is fairly obscure and not widely used AFAIK. wmctrl
has been around longer, is more mature, more people know about it and it will likely be easier to explain your case in terms of wmctrl
. The hope is that wmctrl
is a proxy for your actual issue, in that if you figure out how to solve it with wmctrl
, then it should be somewhat straight-forward to convert that solution to xgbutil.
Thanks.
I have managed to have the same behaviour between i3 and xgbutil by modifying the HINTS with xgbutil. I have added a precise usecase and way to reproduce the issue on the i3 bug https://github.com/i3/i3/issues/4213#issuecomment-706128805
I simply hope this is not having a link with X server request handling as It will be very difficult to find a workaround.
You might also consider trying a range of different widths. Try 640, 641, 642, ..., 670 or whatever. Do any of those result in an initially correct geometry after the first moveresize command? If one does, then maybe it turns out you were misinterpreting how the size hint increments were applied.
Also, IIRC, setting the size hint increments to 1
on the client is not something that worked for me. But the last time I tried that was probably 10 years ago and I've since forgotten the details. It could be that the client will fight with you and set the hints back to what it wants once it sees that they have changed. So you might want to at least verify that that isn't happening.
I think that fundamentally, you cannot expect to have a pixel perfect positioning of clients unless you are the WM.
I'll try with different size. But tweaking the HINTS to 1 definitely impacts the behaviour of i3. The little PoC I wrote illustrates it .
It does seem to apply the increment. Tried 640 to 646 and it really applied 637 and then jumped to 645 (the increment is 8) However 640 is divisible by 8, not 645 so I don't understand why it will stick with an origin different than 0.
I know that the last comment to this thread was a significant amount of time ago, but I found this thread while searching the internet. It came up because OP's issue is the exact same one I am...was having but with using the xcb api directly instead of using this Go wrapper. However, I think the concept of my fix can be translated over. So I'm adding that in the off-chance that some other person has the same issue I've been having and also stumbles onto here.
What I do before closing a connection is to ask for the currently focused window, then wait for that reply. I know that because that's the last reply I sent out, if I wait for it, all my requests must have been processed. This is what the other program was doing, which I verified using xtrace
(great program btw, very useful). The down side is that I can't say this is my idea since it was copied from another program. Oh well.
In C, that looks like this:
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
I don't know what that translates into in terms of this particular binding, but my C code using ewmh went from periodically running to running every single time.
@FascinatedBox thanks for pitching in. Although, I'm not sure what your comment has to do with window resizing and geometry?
When I run one time my program, the window is moved in the correct place however the size is not correct. Geometry functions report a bogus size. If I run a second time the program immediately after, I can see the window changing a liittle bit its size again to finally get the correct size.
I read this as OP having the same issue that I was having earlier (changes not being taken because the program exits before they can be taken in). Reading a bit more, I think I jumped the gun. Sorry.
Hi !
I am trying to resize and move window using xgbutil and facing some issues about it. I am running i3wm and use pkg.go.dev/go.i3wm.org/i3/ to obtain the focused window ID. Then I resize the window using one of the several methods provided by xgbutil.
My issue is : I have a window of random size, I want to move it and set it to a specific size, let's say 640x360. When I run one time my program, the window is moved in the correct place however the size is not correct. Geometry functions report a bogus size. If I run a second time the program immediately after, I can see the window changing a liittle bit its size again to finally get the correct size. Geometry functions returns the same value as before but this time it is correct. Subsquent run does not change the size anymore.
I have printed the geometry of the window before and after the call to the resize function and can see the second time that the size was incorrect (geometry reports the incorrect size). I don't understand why the geometry after the call in the first run is incorrect though.
Let's wrap-up: I create two sets of objects to be sure I am not reusing bufferized values. My code is
First run I got:
I do not touch anything and a rerun the program, I got:
I am a little bit confused in front of the multiple function to resize a window. I found: ewmh.MoveresizeWindow ewmh.MoveresizeWindowExtra ewmh.WmMoveresizeWindow ewmh.WmMoveresizeWindowExtra ewmh.ResizeWindow xwindow.Resize xwindow.MoveResize xwindow.WMResize xwindow.WMMoveResize
I understand some of the differences (such as between Move and MoveResize) but I do not understand the difference between Resize and WMResize for example.