How to fix the keyboard focus issue with nxclient in rootless mode

I bet you've already noticed the focusing issue with nxclient if you tried to use it in rootless mode, just by running with xinit. The problem occurs when you disconnect from the NX server and start nxclient again: the client does not get the keyboard focus no matter what.

This caused me quite some headache and several hours of debugging. I noticed by accident that if I start rdesktop in full-screen mode after I disconnected from an NX session, it "repaired" the focus issue with nxclient. One does not have to actually log in to any server with rdesktop, you just have to make it switch to full-screen mode and you're all done (can exit the RDP session). This was my first clue.

Parallely I started looking for traces of the issue on the net. I've found a thread at the ltsp-discuss mailing list where Gideon Romm mentioned the issue. He's the developer and maintainer of the NX_LTSP package which provides a pre-packaged nxclient for an LTSP environment. He solved the problem by adding a window manager (twm) to the xinit startup script. This is something that I did not want to choose since I had no use for a window manager except for this fix. I knew there had to be another way.

I've found a post in Nomachine's knowledge base where they describe the very same issue, but in a bit different context. This was the first time I read about the use of the XSetInputFocus() function call as a possible fix.

The next step was to analyze rdesktop (a thousand hurrahs to open source Smile ) and see what exactly it is doing that fixes the issue with nxclient. I've spent several hours with taking apart rdesktop's code (commenting out some parts, compiling, testing whether it still fixes the issue with nxclient, then start over again) and finally came to the conclusion that a call to XSetInputFocus() (what a surprise Laughing out loud) makes the difference (it's the call in the function xwin_process_events() in the handler of the EnterNotify event).

The final step was not much easier, than the previous one: I had to use this function call in a separate program that I could run before (or after) nxclient to fix the focusing problem. Rdesktop used this call:
XSetInputFocus(g_display, g_wnd, RevertToPointerRoot, CurrentTime);

Here g_display specifies the connection to the X server, g_wnd stands for the full-screen window of rdesktop, RevertToPointerRoot is a focus-reverting policy and CurrentTime is the actual time of the X server). You can read more about XSetInputFocus and its parameters in the Xlib Programming Manual.

Of course this did not work for me. Smile I tried setting the focus to the root window (XSetInputFocus(display, DefaultRootWindow(display), RevertToPointerRoot, CurrentTime);), setting the focus to nxclient's window (which can be found by going through the result of XQueryTree executed on the root window and looking for a window with a class "nxclient") and a number of combinations.

The problem was with the revert policy: I changed RevertToPointerRoot to RevertToParent and it started to work all of a sudden. Smile So the proper code is:
XSetInputFocus(display, PointerRoot, RevertToParent, CurrentTime);
You can find the full source packaged into a ZIP and attached to this post.

Use of the utility is pretty obvious: start it prior to starting nxclient. Smile

Btw. this was my first encounter with X programming and I've quickly learnt that I do not want to get more familiar with it in near future ... Wink

AttachmentSize
fix-focus-1.0.0.zip8.1 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Thanks.

Thanks for a) spending the time on this and b) publishing your fix.

It just saved me a minor headache setting up an NX connection.

Ta.