Xpra: Ticket #718: focus change requests in java applications does not work

As per the (ugly) example application attached to this ticket, it is impossible to request a raise window in Java using Window.toFront.

Usage:

javac ToolbarFrame1.java
java ToolbarFrame1

Then click raise on one of the windows (only one of the two works... because of lazy coding)



Tue, 21 Oct 2014 14:30:51 GMT - Antoine Martin: attachment set

example Java raise application


Tue, 21 Oct 2014 14:34:04 GMT - Antoine Martin: owner, status, description changed


Tue, 21 Oct 2014 14:40:55 GMT - Antoine Martin: description changed

The fix looks quite simple:

--- xpra/x11/gtk_x11/window.py	(revision 7956)
+++ xpra/x11/gtk_x11/window.py	(working copy)
@@ -624,7 +624,10 @@
     def do_xpra_focus_in_event(self, event):
         grablog("focus_in_event(%s) mode=%s, detail=%s",
             event, GRAB_CONSTANTS.get(event.mode), DETAIL_CONSTANTS.get(event.detail, event.detail))
-        self.may_emit_grab(event)
+        if event.mode==NotifyNormal and event.detail==NotifyNonlinearVirtual:
+            self.emit("raised", event)
+        else:
+            self.may_emit_grab(event)
     def do_xpra_focus_out_event(self, event):
         grablog("focus_out_event(%s) mode=%s, detail=%s",

But this is similar to grabs (#139 - see also #556) so maybe there are corner cases, and maybe this can cause regressions with clients that deal with focus client side? Will need testing with some of the test apps (and maybe write new ones for it).

So I am not applying it just yet.


Tue, 28 Oct 2014 14:12:53 GMT - Antoine Martin:

Worth mentioning: jdk7 known issues:. Quoting here since there is no internal link:

Area: API: AWT

Synopsis: This issue is specific to Window.toFront() and Window.toBack() behavior on X11 systems (Linux, Solaris). AWT always performs all necessary actions required to bring a window to the top or the bottom in the stacking order, according to the specifications of the windowing systems (e.g. the ICCCM and/or the EWMH for X11 systems). Whether the actions take effect or not depends on the window manager currently running in the system. Some windowing systems enforce additional constraints on when a window may be brought to the top in the window stacking order. In most cases, the purpose for such additional constraints is to enhance usability or security of these windowing environments. In other cases, these may simply be bugs in the windowing systems. This means that invoking the Window.toFront() or Window.toBack() methods may not always produce the expected results. While this issue is, to some extent, reflected in the specification of the toFront() method, we've received several user complaints on this particular behavior while developing JDK7. All of these CRs have been closed as "Not a Defect" because AWT can't short-circuit the additional constraints, or work around any bugs in third-party software. If the problem is encountered with a Java application, in most cases it makes sense to check if native applications behave the same way, and file a bug against the windowing system accordingly.


Sun, 02 Nov 2014 10:28:20 GMT - Antoine Martin:

The first difficulty is in finding some test code that does raise another window, even when minimized. Sounds simple, but it isn't in Java. See How to bring a window to the front? When the window is minimized using the client window manager rather than programmatically (as apposed to How do I minimize and restore frames and JFrames?), the only thing that does restore it is to hide it then show it again, otherwise Java just doesn't change its state... (see RaiseTest.java)

Also it seems there are a few Java bugs in this area:

Now, we do fail this test. Adding the patch from comment:2 does improve things, but not it isn't very reliable and we don't handle the window when minimized, because we don't actually minimize it server side...


Mon, 03 Nov 2014 16:11:29 GMT - Antoine Martin:

I am moving the lack of support for setting the minimized state of windows to #726. This should resolve the raising of minimized windows (assuming this ticket is also fixed).

Running the example above under xtrace, I see that the request to raise the window is done using a XConfigureRequestEvent with stack-mode=Above:

000:<:04c9: 16: Request(12): ConfigureWindow window=0x00800007 values={stack-mode=Above(0x00)}

So we should be able to select for those events on the window.. except I can't seem to receive them!? The window in the request data is the "client window" as found in our window model, that's the application's own window. According to the docs ConfigureRequest Events: To receive ConfigureRequest events, set the SubstructureRedirectMask bit in the event-mask attribute of the window. ConfigureRequest events are generated when a ConfigureWindow protocol request is issued on a child window by another client. For example, suppose a client application calls XLowerWindow() to lower a window. If you had selected SubstructureRedirectMask on the parent window and if the override-redirect attribute of the window is set to False, the X server reports a ConfigureRequest event to you and does not lower the specified window.

We do already select those events using X11Window.substructureRedirect, this is how we already intercept client applications that resize themselves, but I am not seeing the stack-raise event in the X11 filter! Why!?


Tue, 04 Nov 2014 07:27:29 GMT - Antoine Martin:

Improved the test examples in r8050 + r8051.

Running the GTK resize test and xtracing it with:

xtrace ./tests/xpra/test_apps/test_window_resize.py |& \
    egrep -vi "render|keyboard|cliprect|copyarea|changegc|pixmap|polyfill|motionnotify|expose|polysegment"

I see the configure request, but still not in the xpra event loop. At least it is consistent.


Sat, 27 Dec 2014 17:03:55 GMT - Antoine Martin:

Running the raise test example, I can see that Java fails to see our window as iconified.

There is a difference between what a normal desktop environment does and what we do when minimizing a window:

In all cases:


Sun, 28 Dec 2014 16:57:29 GMT - Antoine Martin:

See #726 for the fix to WM_STATE. Now going back to the actual toFront to try to find a cleaner solution for detecting the "window raise" event.

The relevant code for toFront() in the Java source looks like this one in solaris/classes/sun/awt/X11/XBaseWindow.java using XRaiseWindow:

public void toFront() {
    XToolkit.awtLock();
    try {
        XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow());
    } finally {
        XToolkit.awtUnlock();
    }
}

This should allow us to write a simple example to test with.


Thu, 01 Jan 2015 16:57:54 GMT - Antoine Martin:

The improvements done as part of #765 (in particular r8319) now allow Java to see the window as iconified. The updated example code correctly unminimizes the window before trying to raise it. But the raising part is still problematic..


Thu, 01 Jan 2015 17:16:33 GMT - Antoine Martin: attachment set

updated test code, which does raise the window even when it is minimized


Thu, 01 Jan 2015 17:17:29 GMT - Antoine Martin: owner, status changed

Having read again (with difficulty) Normal Focus Events and Focus Events While Grabbed, I believe the change from comment:2 may well be correct in the end so I've applied it in r8351. (it could be backported - but not need to rush it)

afarr: just re-assigning to you so you know about this, in case we hit focus related issues somewhere else - this could be the cause. Feel free to just close it as an ACK. To run the example test code, just run:

javac RaiseTest.java
java RaiseTest

Mon, 05 Jan 2015 05:34:21 GMT - Antoine Martin:

I've not seen any adverse effects so far, so backported to v0.14.x in r8384.


Mon, 05 Jan 2015 06:06:29 GMT - Antoine Martin:

Spoke too soon: r8286 (+backport in r8287) needed to prevent minimize + restore loops when minimizing a window which does not have focus.


Wed, 18 Feb 2015 02:23:05 GMT - alas:

Err... think I'm doing something wrong trying to launch.

Running: $ java ToolbarFrame1.java I get Error: Could not find or load main class ToolbarFrame1.java.

(Google says something about javac, but that's giving me a command not found error... I know I'm missing something.)


Wed, 18 Feb 2015 04:23:14 GMT - Antoine Martin:

Please see comment:10, you need to run javac before you can run java on the class file that gets generated.

javac, but that's giving me a command not found error..


Which package provides javac depends on what distro you are testing with.


Mon, 23 Feb 2015 23:03:37 GMT - alas: owner changed

Ok... run and now vaguely familiar with it. Handing back to you to close (assuming you don't have more bits to handle).


Tue, 24 Feb 2015 00:55:47 GMT - Antoine Martin: status changed; resolution set

Done! Closing.


Sat, 23 Jan 2021 05:03:55 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/718