JDK-8115852 : PopupWindow with content with Shadow Effect, wrong position
  • Type: Bug
  • Component: javafx
  • Sub-Component: scenegraph
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-03-05
  • Updated: 2015-06-17
  • Resolved: 2013-03-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
When a menu's content has a shadow effect or similar that draws outside of layout bounds. We move the node down so that the whole node is inside the popup window and we do not get clipping of the shadow. The problem with this is a shadow on a menu offsets the menu so that it no longer aligns with the menu bar. See the attached screenshots.

What should happen is the popup should be moved from the user set X,Y so that the layout bounds 0,0 is positioned at the user requested screenX, screenY. 

I did a simple patch for this:

diff -r 649ecc9fc736 javafx-ui-common/src/javafx/stage/PopupWindow.java
--- a/javafx-ui-common/src/javafx/stage/PopupWindow.java	Mon Mar 04 15:17:00 2013 -0800
+++ b/javafx-ui-common/src/javafx/stage/PopupWindow.java	Mon Mar 04 16:57:25 2013 -0800
@@ -341,7 +341,11 @@
         if (ownerNode != null) { 
             ownerNode.visibleProperty().addListener(ownerNodeListener);
         }
-       
+
+        Bounds sceneRootBounds =  getScene().getRoot().getBoundsInLocal();
+        if (sceneRootBounds.getMinX() < 0) screenX += sceneRootBounds.getMinX();
+        if (sceneRootBounds.getMinY() < 0) screenY += sceneRootBounds.getMinY();
+
         setX(screenX);
         setY(screenY);
         showImpl(newOwnerWindow);

I am not sure this is the right place for this fix and looked a bit deeper. It seems like we have very similar code:

            if (!isAutoFix()) {
                final Parent rootNode = getScene().getRoot();
                if (rootNode != null) {
                    final Bounds _bounds = rootNode.getLayoutBounds();
                    setX(this.getX() + _bounds.getMinX());
                    setY(this.getY() + _bounds.getMinY());
                }
            }

At line 403 of PopupWindow.java but its not running because isAutoFix() is true. Looking at the history it looks like this code used to always be run but got moved behind this if statement with a fix for RT-19437 by Lubomir in change 424:b5bafe2e6c6e. So I am not sure why this got removed. So I am unsure if me putting something similar back in place is a good idea or not. Was this removed for a reason or by accident?


Comments
Verified on 8.0b104
30-08-2013

Fixed as: Changeset: aaf819fd09f9 Author: Lubomir Nerad <lubomir.nerad@oracle.com> Date: Mon Mar 25 14:36:57 2013 +0100 URL: http://jfxsrc.us.oracle.com/javafx/8.0/scrum/graphics/rt/rev/aaf819fd09f9 Description: Fix for RT-28775: PopupWindow with content with Shadow Effect, wrong position The requested API change tracked as RT-29194.
25-03-2013

I spoke to Richard and Steve Northover about this. We are all happy that it changes the X|Y of the Popup directly. We also think there should be a boolean property to switch the behavior off. Its default should be ON.
07-03-2013

I agree with the first part, but I don't think we can change the meaning of getX|Y and setX|Y which is specified in Window. Also it would probably require an ugly hack to implement. Could you check with Richard what is his opinion about these issues?
07-03-2013

I think we should move window based on the layout bounds always. Also we should listen to changes in bounds and update. It would be nice if this could be hidden from the user in that getX|Y would return what they set via setX\Y and there would be a secondary shift after that for the layout bounds.
06-03-2013

Before my change (http://jfxsrc.us.oracle.com/javafx/2.1/scrum/graphics/rt/rev/b5bafe2e6c6e), the adjustment for layout bounds was already only in the else block of the "if (isAutoFix()) { ... } else { ... }" statement. I only extracted the first branch and left the else block in place. The layout bounds adjustment was removed from the first branch in http://jfxsrc.us.oracle.com/javafx/2.1/scrum/graphics/rt-closed/rev/8c20be88427a (fix for RT-12649). I don't know whether that was intentional or not, but I think that we should have the correction either in both cases (independent on the autoFix value) or not at all. Now if we want to have the correction, we should decide what to do when the layout bounds of the root node change. Do we automatically move the window, so the content area stay pinned to the coordinates specified in show? There is already some code in PopupWindow which changes the size of the window automatically if the layout bounds change, so correcting the position as well might provide more consistent behavior. Another problem is that if we do the position adjustment in show, we will make the coordinates passed to show different from coordinates which are reported or set through the Window.x, Window.y (position of content area vs. position of the whole window). Are we OK with that?
06-03-2013

After we fix this we will also need to remove the (-10) hack from ComboBoxPopupControl.java line 90: return com.sun.javafx.Utils.pointRelativeTo(getSkinnable(), getPopupContent(), HPos.CENTER, VPos.BOTTOM, dx, -10, false); which was a hack workaround for this issue, hard coded for caspian.css
05-03-2013

Assigning to Lubo so that he can have a look as he changed this code last.
05-03-2013