ArcticaProject / nx-libs

nx-libs
Other
120 stars 39 forks source link

Tricky minimize/maximize/restore things in rootless #1015

Open dimbor-ru opened 3 years ago

dimbor-ru commented 3 years ago

Some programs are now ashamed to use wm and its buttons to perform these operations. They at least continue to use the ICCCM and Extended WM hints specifications. Namely WM_CHANGE_STATE and _NET_WM_STATE client messages sent to root window. Attached are two green buttons to illustrate this "outrageous" behavior. It not worked in rootless on linux nx-client (naturally on nxwin too).

I started exploring ways to solve the problem. Can be forcibly replaced root window in these client messages and deliver them to real wm. The only thing that stops me is that a similar question has already been discussed here: #830 I don't want to break something globally with my future patches and I want to hear your opinions.

uli42 commented 3 years ago

I have compiled your test program. It is working fine locally, it is also working fine in a desktop NX session. In a rootless session that has been started from inside the desktop session the buttons of the testprogram seem to have no effect. However, the window manager controls for minimizing and maximizing are still working. Just to be sure: is this the problem you are describing or is this another problem?

I have not checked the source yet.

dimbor-ru commented 3 years ago

Exactly. It is this problem that is being described. Native wm controls are left for contrast only.

dimbor-ru commented 3 years ago

Here's another way to reproduce the problem: In the x terminal rootless session try to operate youreself window by xclimsg.

uli42 commented 3 years ago

Can we simulate your suggested fix with xclimsg?

dimbor-ru commented 3 years ago

Firstly, the fix is still only my fantasy ;)

For example, the maximization case. Simulation done if command xclimsg -m -w <realx_winid> _NET_WM_STATE 1 _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ starting on client of real x-server. On nx-session with of same window command do nothing. These client messages are filtered by nxagent if xev not lying.

Did I answer the question or did not understand it?

uli42 commented 3 years ago

No, I meant: can you fake a command that will send the event the same way a fixed nxagent would do? (if fixed like you mentioned in your first post) e.g running the command on the proxy side with the corresponding proxy side window ids?

dimbor-ru @.***> schrieb am Fr., 30. Apr. 2021, 21:50:

Firstly, the fix is still only my fantasy ;)

For example, the maximization case. Simulation done if command xclimsg -m -w _NET_WM_STATE 1 _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ starting on client of real x-server. On nx-session with of same window command do nothing. These client messages a filtered by nxagent if xev not lying.

Did I answer the question or did not understand it?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ArcticaProject/nx-libs/issues/1015#issuecomment-830343327, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABQHBZHQWEO6DFCHQO2SK6DTLMCWZANCNFSM433EF2AQ .

dimbor-ru commented 3 years ago

I am completely confused. !M uses the following terminology and we have the chain: local x server - local proxy (~nxcomp) - remote proxy (~nxagent) - x-client (our program). Code on local side named nx client, on remote side - nx server. I will now assume that "proxy side"==nx server side. Command xclimsg -t <local_root_wid> -w <any_wid> ... cause error now. Error of failed request: BadWindow (invalid Window parameter) local_root_wid not known to remote.

uli42 commented 3 years ago

I use this terminology:

local ("proxy side"): real Xserver <-> nxproxy <-> (from/to nxagent on the remote side) remote ("agent side"): (from/to nxproxy on the local side) <-> nxagent <-> xclient

Now, what I meant: the xclient sends a client message to the nxagent. It uses window ids only known to the nxagent. nxagent normally translates these window ids to the window ids that are used by the corresponding windows on the real xserver. So by running your example program or xclimsg inside the session you are using inside window ids that are only known by nxagent. Looking from the nxagent's perspective lets call them "internal" window ids. IF the nxagent passes them on to real xserver it first needs to translate the window ids to the ones used on the real xserver, let's call them "external" window ids.

The assumption is that nxagent will not pass on the client messages it receives from xclimsg. So what we can try is to run xclimsg on the real xserver side using the external window ids. Faking the client message that was not forwarded by nxagent.

nxagent knows some helpful command line switches that can help here:

 -nxrealwindowprop
          set property NX_REAL_WINDOW for each X11 client inside

nxagent, providing the window XID of the corresponding window object on the X server that nxagent runs on

  -reportwids
          explicitly tell nxagent to report its externally exposed

X11 window IDs to the session log (in machine readable form), so that external parsers can obtain that information from there

  -reportprivatewids
          explicitly tell nxagent to report X11 window IDs of

internally created window objects to the session log (in machine readable form), so that external parsers can obtain that information from there; this creates a lot of output and may affect performance

On Sat, May 1, 2021 at 4:59 AM dimbor-ru @.***> wrote:

I am completely confused. !M uses the following terminology and we have the chain: local x server - local proxy (~nxcomp) - remote proxy (~nxagent) - x-client (our program). Code on local side named nx client, on remote side - nx server. I will now assume that "proxy side"==nx server side. Command xclimsg -t -w ... cause error now. Error of failed request: BadWindow (invalid Window parameter) local_root_wid not known to remote.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

uli42 commented 3 years ago

Ok, after reading your description again I think you have done the right thing from the beginning. I can replicate your result:

$ nxagent -R :55 -nxrealwindowprop -reportwids -reportprivatewids
...
NXAGENT_WINDOW_ID: PRIVATE_WINDOW,WID:[0xc40004e],INT:[0x200001]  <---
NXAGENT_WINDOW_ID: PRIVATE_WINDOW,WID:[0xc400050],INT:[0x200003]
NXAGENT_WINDOW_ID: PRIVATE_WINDOW,WID:[0xc400051],INT:[0x200004]
...

(:55 is the nxagent's display number, 0x200001 is the internal window id,0xc40004e is the external id)

$ DISPLAY=:55 xclimsg -m -w 0x200001  _NET_WM_STATE 1 _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ

-> nothing happens

$ DISPLAY=:0 xclimsg -m -w 0xc40004e  _NET_WM_STATE 1 _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ

-> window is maximized

uli42 commented 3 years ago

While playing around with this I came across this: Your source code calls XInternAtom(..., True). In a fresh rootless session this cannot work as the atoms will be missing if there's no window manager. So you should call XInternAtom() with False.

dimbor-ru commented 3 years ago

Ok, after reading your description again I think you have done the right thing from the beginning. I can replicate your result: ...

Very good!

  1. Our terminology is synchronized now. (Like local and remote atoms ;)
  2. I learned a lot of interesting about command line options. I would search there lastly, It's true.
  3. The idea of fix has the right to life. Presumable exposure point - nxagentHandleClientMessageEvent().

Your source code calls XInternAtom(..., True). In a fresh rootless session this cannot work as the atoms will be missing if there's no window manager. So you should call XInternAtom() with False.

You're right. I tried to imitate the behavior of proprietary software only. And I can't be sure that there is not written in the same way.

Thanks for all items. I will take a timeout for writing a patch.

dimbor-ru commented 3 years ago

Presumable exposure point - nxagentHandleClientMessageEvent().

Ups! Because of excessive optimism, I confused the direction of the messages. This is normal for me. The necessary client messages are safely caught in NXEvents.c, ProcSendEvent() In this regard, I have another question. Will the community beat me if I try to change wids in the request directly? Or do I need to dance there like nxagentSendNotify()?

uli42 commented 3 years ago

Yes and no. You can use nxagentLocalToRemoteAtom() to map the atoms and for the window mapping stuff there are lots of nxagentWindow* macros.

I have tried to implement this (in ProcSendEvent() yesterday but I failed. It send the message but the WM did not react on it. Hope the best for your approach.

uli42 commented 3 years ago

I have done some tests and now have a patch ready, please have a look.

dimbor-ru commented 3 years ago

Nuts! Everything is working. You have saved a lot of my time. Now I can add handling these messages to nxwin and its pseudo-wm. But in reality, to steal from dad-xwin creatively.

dimbor-ru commented 3 years ago

I have added client messages handling to nxwin multiwindow mode. There, the code is no longer "academic", but is still used in OpenNX for Windows and in NXClientCE. No problems have been noticed yet.

uli42 commented 3 years ago

Good to hear that. So what do you think: can my patch be merged or does it need some refinement?

On Fri, May 7, 2021 at 12:01 PM dimbor-ru @.***> wrote:

I have added client messages handling to nxwin http://git.etersoft.ru/people/dimbor/packages/?p=NXClient-W32.git;a=summary multiwindow mode. There, the code is no longer "academic", but is still used in OpenNX for Windows https://unixforum.org/up/nxman/OpenNXCE-1.0.0-r15.6.exe and in NXClientCE https://unixforum.org/up/nxman/NXClientCE-3.5.0-9-r15.6.exe. No problems have been noticed yet.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ArcticaProject/nx-libs/issues/1015#issuecomment-834231262, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABQHBZFEYDXD5EOVKBIY3XDTMO3AVANCNFSM433EF2AQ .

dimbor-ru commented 3 years ago

It feels good. I do not know what to find fault with. Thanks again.

uli42 commented 3 months ago

I have come across a problem with this patch: I was trying to run xxdiff 50b1 (https://github.com/blais/xxdiff resp. https://furius.ca/xxdiff/) and ended up with a crashing nxagent I looks like pWin is unset in Events.c:4511.

uli42 commented 3 months ago
#0  ForwardClientMessage (client=0x2d47b20, stuff=0x2fb6708) at Events.c:4511
#1  0x0000000000423af7 in ProcSendEvent (client=0x2d47b20) at NXevents.c:430
#2  0x0000000000431ce3 in Dispatch () at NXdispatch.c:488
#3  0x000000000040f10a in main (argc=20, argv=0x7ffe1a48e478, envp=<optimized out>) at main.c:350

This happens because pWin is 0x0 in ForwardClientMessage. I can trigger this by running xxdiff 50b1 from https://github.com/blais/xxdiff on Rocky8.9.