JDK-8170972 : ComboBox dropdown wrong location in RTL popup
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 8,9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2016-12-08
  • Updated: 2018-09-05
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.
Other
tbdUnresolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-3-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux 4.8.0-1-amd64 #1 SMP Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
ComboBox inside a Popup or PopupControl displays its dropdown in the wrong location, if root of Popup has RTL orientation. 

Illustration available here: http://imgur.com/a/Lolq6  

This looks similar to JDK-8125934 , but it still occurs in 8u111, so it's either a new similar bug, or a regression.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See attached demo code. 

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Drop down should appear below combobox. 
ACTUAL -
Drop down appears far from the combobox, about (size of Popup) pixels to the left

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package sample;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.NodeOrientation;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.PopupControl;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.PopupWindow;
import javafx.stage.Stage;


public class Demo extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Button b = new Button("Click me");
        b.setOnAction(event -> {
            PopupControl popup = new PopupControl();
            popup.setAnchorLocation(PopupWindow.AnchorLocation.CONTENT_TOP_RIGHT);
            popup.setAutoHide(true);
            ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("foo", "bar"));
            HBox box = new HBox(5, new Label("Select value"), cb);
            box.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
            // This is only to make the popup more visible. Removing it doesn't change the occurrence of the bug.
            box.setStyle("-fx-background-color: derive(-fx-background, 30%); -fx-border-color: black; -fx-border-width: 1px;");
            popup.getScene().setRoot(box);

            Point2D anchor = b.localToScreen(b.getWidth(), b.getHeight());
            popup.show(b, anchor.getX(), anchor.getY());
        });
        ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("foo", "bar"));
        VBox vb = new VBox(10, b, cb);
        vb.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
        Scene scene = new Scene(vb, 200, 200);
        stage.setScene(scene);

        stage.show();
    }


    public static void main(String[] args) throws Exception {
        launch(args);
    }

}

---------- END SOURCE ----------


Comments
I suspect that the last comment (in the 'note' section) might be making one too many leaps of faith. In particular, yes, getWindow() by definition returns Window, but changing the instanceof check from checking if the Window is an instanceof Stage to checking if it is an instanceof Window means we are no longer able to discern between the different subclasses of Window, that is, PopupWindow (and its subtypes), and Stage. There would need to be quite some testing involved to ensure there are no visual regressions, and my gut feeling is that we might hit some with this kind of change.
12-12-2016

Comment (and attachment) from Itai: ================================== It seems to me the source of the problem is line 466 in com.sun.javafx.util.Utils: //TODO - testing for an instance of Stage seems wrong but works for menus if (scene.getWindow() instanceof Stage) { layoutX = layoutX + parentBounds.getWidth() - anchorWidth; } else { layoutX = layoutX - parentBounds.getWidth() - anchorWidth; } As Popup is a Window but not a Stage, the proposed fix is to simply change the condition to: if (scene.getWindow() instanceof Window) Obviously tests need to be run to see this doesn't break anything else, but I'm not sure how to do so. As I can't post this to the JDK bug tracking system I'm sending this here, so I'll appreciate it is someone with access can post it there. If it does pass all tests, and considering it's a pretty simple change, I'd greatly appreciate if it could find its way into the next 8 update, as it is currently blocking a feature in a project I'm working on. Note: I'm not sure if I have used the most up-to-date dev version for the patch file. Also, the test itself may be redundant, as getWindow() should always return Window, shouldn't it? Regards, Itai.
09-12-2016

Verified this issue against 8,8u112,8u122ea,9ea on Windows 7 and could confirm the issue as reported by the bug submitter. Steps to reproduce: ********************** - run the attached file(Demo.java) with JDK. Result: ********* OS : Microsoft Windows 7 Professional 64 bit [Version 6.1.7601] JDK: ++++ 8 b132 : Fail 8u112 b15 : Fail 8u122ea b02 : Fail 9ea+146 : Fail ==============================================================
09-12-2016