Proposal For Inclusion of Robot and ParametersImpl in the Public API

Kevin Rushforth kevin.rushforth at oracle.com
Wed Dec 20 22:05:35 UTC 2017


Sure, no problem. One quick comment is that a common way to solve this 
is by delegating to an implementation class, which would then be 
sub-classes.

-- Kevin


Michael Ennen wrote:
> I am not trying to be a burden here. I understand that you may not 
> have time to hand-hold
> to this degree. I will try and make progress, sorry for the follow up 
> question.
>
> On Wed, Dec 20, 2017 at 2:08 PM, Michael Ennen <mike.ennen at gmail.com 
> <mailto:mike.ennen at gmail.com>> wrote:
>
>     How can Robot call into the implementation when it is a super
>     class of the implementations?
>
>     On Wed, Dec 20, 2017 at 2:04 PM, Kevin Rushforth
>     <kevin.rushforth at oracle.com <mailto:kevin.rushforth at oracle.com>>
>     wrote:
>
>
>
>         Michael Ennen wrote:
>>         I have a question about how to proceed with the Robot code.
>>
>>         The base abstract Robot class
>>         is: https://github.com/brcolow/openjfx/blob/master/modules/javafx.graphics/src/main/java/javafx/scene/robot/Robot.java
>>         <https://github.com/brcolow/openjfx/blob/master/modules/javafx.graphics/src/main/java/javafx/scene/robot/Robot.java>
>>
>>         As you can see for each method, such as "getMouseX()" there
>>         is a "_" prefixed method
>>         which is abstract and a non-prefixed method:
>>
>>         protected abstract int _getMouseX();
>>
>>         public int getMouseX() {
>>             Application.checkEventThread();
>>             return _getMouseX();
>>         }
>>
>>         I have copied this from the private Robot API.
>>
>>         Is there a better way to do this? Would this pass review?
>
>         Yes there are better ways to do this. No it would not pass
>         review, since this would be leaking implementation into the
>         public API.
>
>         Rather than copying the public / protected methods from the
>         internal package, it probably makes more sense to start with
>         what a Robot API should look like and then have that call into
>         the implementation (suitably modified so it better matches the
>         public API). For one thing you will then leave the
>         implementation, including the per-platform code, where it
>         belongs -- in glass. The Robot API can be informed by the
>         current implementation, but should not be defined by it.
>
>         -- Kevin
>
>
>>
>>         Thanks very much.
>>
>>
>>         On Tue, Dec 5, 2017 at 5:29 PM, Kevin Rushforth
>>         <kevin.rushforth at oracle.com
>>         <mailto:kevin.rushforth at oracle.com>> wrote:
>>
>>             Glad you got the build working. You can post back on this
>>             thread when you are ready.
>>
>>
>>             -- Kevin
>>
>>
>>             Michael Ennen wrote:
>>>             Correction:
>>>
>>>             Adding ""--add-exports
>>>             javafx.graphics/javafx.scene.robot=ALL-UNNAMED" to
>>>             buildSrc/addExports.
>>>
>>>             For posterity :)
>>>
>>>             On Mon, Dec 4, 2017 at 6:08 PM, Michael Ennen
>>>             <mike.ennen at gmail.com <mailto:mike.ennen at gmail.com>> wrote:
>>>
>>>                 Ah, indeed, missed adding "--add-opens
>>>                 javafx.graphics/javafx.scene.robot=ALL-UNNAMED" to
>>>                 buildSrc/addExports.
>>>                 Thanks for the guidance on that.
>>>
>>>                 I will continue to work on this in the GitHub repo
>>>                 and polish it up (add javadocs, better method
>>>                 signatures, etc.) and 
>>>                 even plan on maybe improving the underlying native
>>>                 Robot implementations (for example fixing/improving the
>>>                 way color profiles are handled for MacRobot).
>>>
>>>                 I will also take a look at "fixing" JemmyFX to use
>>>                 the new public API (as well as any other place in
>>>                 the JavaFX code
>>>                 base that does).
>>>
>>>                 I was expecting that JDK 11 would be the appropriate
>>>                 time frame, especially because it will be the
>>>                 release where
>>>                 private APIs will be totally inaccessible, correct?
>>>
>>>                 After I get it in a reasonable state should I post
>>>                 back on this mailing list thread or what would be
>>>                 the appropriate
>>>                 way?
>>>
>>>                 Thanks Kevin.
>>>
>>>                 On Mon, Dec 4, 2017 at 5:12 PM, Kevin Rushforth
>>>                 <kevin.rushforth at oracle.com
>>>                 <mailto:kevin.rushforth at oracle.com>> wrote:
>>>
>>>                     This is a limitation of the the way
>>>                     --patch-modules works. You will need to add an
>>>                     entry in:
>>>
>>>                     buildSrc/addExports
>>>
>>>                     Btw, as for the proposal itself, this might need
>>>                     to be a JEP depending on the scope. In any case,
>>>                     it could be considered in the JDK 11 time frame,
>>>                     but there are several things that need to be
>>>                     worked out before making Robot a public API,
>>>                     including the fact that the JemmyFX framework in
>>>                     the openjfx/jfx/tests directory uses Robot. Once
>>>                     you get a working prototype, it would be
>>>                     interesting to discuss it in more detail.
>>>
>>>                     -- Kevin
>>>
>>>
>>>
>>>                     Michael Ennen wrote:
>>>>                     Currently I am stuck with tests not being able to see the new
>>>>                     "javafx.scene.robot" module:
>>>>
>>>>                       
>>>>>                     Task :systemTests:compileTestJava
>>>>>                         
>>>>                     C:\Users\brcolow\dev\openjfx\tests\system\src\test\java\test\robot\com\sun\glass\ui\monocle\ModalDialogTest.java:34:
>>>>                     error: package javafx.scene.robot is not visible
>>>>                     import javafx.scene.robot.Robot;
>>>>                                        ^
>>>>                       (package javafx.scene.robot is declared in module javafx.graphics, which
>>>>                     does not export it)
>>>>                     C:\Users\brcolow\dev\openjfx\tests\system\src\test\java\test\robot\com\sun\glass\ui\monocle\RobotTest.java:33:
>>>>                     error: package javafx.scene.robot is not visible
>>>>                     import javafx.scene.robot.Robot;
>>>>
>>>>                     I have added:
>>>>
>>>>                         exports javafx.scene.robot;
>>>>
>>>>                     to: modules/javafx.graphics/src/main/java/module-info.java
>>>>
>>>>                     But this does not seem to be enough.
>>>>
>>>>                     On Sun, Dec 3, 2017 at 4:48 PM, Michael Ennen <mike.ennen at gmail.com> <mailto:mike.ennen at gmail.com> wrote:
>>>>
>>>>                       
>>>>>                     I am still working on all the necessary changes to actually allow openjfx
>>>>>                     to compile.
>>>>>                     Tons to learn in that arena and I know the code as it is written won't
>>>>>                     totally work.
>>>>>                     For example one can no longer:
>>>>>
>>>>>                     #include "com_sun_glass_ui_Robot.h"
>>>>>
>>>>>                     as in openjfx\modules\javafx.graphics\src\main\native-glass\win\Robot.cpp
>>>>>
>>>>>                     But I am not sure how those headers are generated and if I can just simply
>>>>>                     change
>>>>>                     it to "#include javafx_scene_robot_Robot.h" (which I very much doubt).
>>>>>
>>>>>                     On Sun, Dec 3, 2017 at 2:29 PM, Michael Ennen <mike.ennen at gmail.com> <mailto:mike.ennen at gmail.com>
>>>>>                     wrote:
>>>>>
>>>>>                         
>>>>>>                     I have created a (small) proposal (building on the work of Benjamin
>>>>>>                     Gudehaus) about moving some classes in to the public API so that TestFX (a
>>>>>>                     JavaFX UI testing framework) can continue to work with future JDK releases.
>>>>>>                     The somewhat nicely formatted proposal can be found as a Github gist:
>>>>>>
>>>>>>                     https://gist.github.com/brcolow/26370db6cab0355186d4a1d13b30fc19 <https://gist.github.com/brcolow/26370db6cab0355186d4a1d13b30fc19>
>>>>>>
>>>>>>                     All suggested changes can be found by using Github Compare View:
>>>>>>
>>>>>>                     https://github.com/brcolow/openjfx/compare/4ccdbbbce5234e2c5 <https://github.com/brcolow/openjfx/compare/4ccdbbbce5234e2c5>
>>>>>>                     e1f4f1cb8f20430feaa53b6...master
>>>>>>
>>>>>>                     But I have copied it to this email for convenience:
>>>>>>
>>>>>>                     ----------------------- PROPOSAL -----------------------
>>>>>>
>>>>>>                     TestFX, the JavaFX GUI testing framework currently requires 4 (four)
>>>>>>                     classes that are part of the JDK's private API. They are:
>>>>>>
>>>>>>                     [com.sun.glass.ui.Application](http://hg.openjdk.java.net/op
>>>>>>                     enjfx/10-dev/rt/file/tip/modules/javafx.graphics/src/main/
>>>>>>                     java/com/sun/glass/ui/Application.java)
>>>>>>                     [com.sun.glass.ui.Pixels](http://hg.openjdk.java.net/openjfx <http://hg.openjdk.java.net/openjfx>
>>>>>>                     /10-dev/rt/file/tip/modules/javafx.graphics/src/main/java/
>>>>>>                     com/sun/glass/ui/Pixels.java)
>>>>>>                     [com.sun.glass.ui.Robot](http://hg.openjdk.java.net/openjfx/ <http://hg.openjdk.java.net/openjfx/>
>>>>>>                     10-dev/rt/file/tip/modules/javafx.graphics/src/main/java/com
>>>>>>                     /sun/glass/ui/Robot.java)
>>>>>>                     [com.sun.javafx.application.Pa <http://com.sun.javafx.application.Pa>rametersImpl](http://hg.openjd
>>>>>>                     k.java.net/openjfx/10-dev/rt/file/tip/modules/javafx.
>>>>>>                     graphics/src/main/java/com/sun/javafx/application/ParametersImpl.java <http://k.java.net/openjfx/10-dev/rt/file/tip/modules/javafx.graphics/src/main/java/com/sun/javafx/application/ParametersImpl.java>)
>>>>>>
>>>>>>                     In order to compile the project with Java 9, we use the following flags:
>>>>>>
>>>>>>                     ```sh
>>>>>>                     --add-exports javafx.graphics/com.sun.glass.ui=org.testfx
>>>>>>                     --add-exports javafx.graphics/com.sun.javafx.application=org.testfx
>>>>>>                     ```
>>>>>>
>>>>>>                     If the --add-exports flags are disabled in a future Java release TestFX
>>>>>>                     will require these four classes to be moved into the public API to
>>>>>>                     continue working.
>>>>>>
>>>>>>                     While these classes are probably not very useful for applications to use
>>>>>>                     directly, any JavaFX application wanting to write UI tests will most
>>>>>>                     likely
>>>>>>                     use TestFX and thus they will indirectly be using these classes.
>>>>>>
>>>>>>                     JavaFX internal tests also use these classes for essentially the same
>>>>>>                     purpose (UI tests).
>>>>>>
>>>>>>                     ### Details of Usage For Each Private API Class
>>>>>>
>>>>>>                     #### com.sun.javafx.application.ParametersImpl
>>>>>>
>>>>>>                     ##### TestFX Usage
>>>>>>
>>>>>>                     ```java
>>>>>>                     ParametersImpl parameters = new ParametersImpl(applicationArgs);
>>>>>>                     ParametersImpl.registerParameters(application, parameters);
>>>>>>                     ```
>>>>>>
>>>>>>                     The parameters are set on a constructed Application.
>>>>>>
>>>>>>                     ##### Suggested Public API Replacement
>>>>>>
>>>>>>                     `javafx.application.Application`:
>>>>>>
>>>>>>                     ```java
>>>>>>                     /**
>>>>>>                      * Sets the parameters for this Application.
>>>>>>                      *
>>>>>>                      * <p>
>>>>>>                      * NOTE: this method should not be called from the Application
>>>>>>                     constructor,
>>>>>>                      * as it will return null. It may be called in the init() method or any
>>>>>>                      * time after that.
>>>>>>                      * </p>
>>>>>>                      *
>>>>>>                      * @param parameters the parameters to set for this Application
>>>>>>                      */
>>>>>>                     public final Parameters setParameters(String... parameters) {
>>>>>>                         ParametersImpl parameters = new ParametersImpl(parameters);
>>>>>>                         ParametersImpl.registerParameters(this, parameters);
>>>>>>                     }
>>>>>>                     ```
>>>>>>
>>>>>>                     #### com.sun.glass.ui.Application
>>>>>>
>>>>>>                     ##### TestFX Usage
>>>>>>
>>>>>>                     ```java
>>>>>>                     return Application.GetApplication().createRobot();
>>>>>>                     ```
>>>>>>
>>>>>>                     The Application class is used to instantiate a Robot.
>>>>>>
>>>>>>                     ##### Suggested Public API Replacement
>>>>>>
>>>>>>                     `javafx.application.Application`:
>>>>>>
>>>>>>                     https://github.com/brcolow/openjfx/blob/master/modules/javaf <https://github.com/brcolow/openjfx/blob/master/modules/javaf>
>>>>>>                     x.graphics/src/main/java/javafx/application/Application.java#L527
>>>>>>
>>>>>>                     #### com.sun.glass.ui.Pixels
>>>>>>
>>>>>>                     ##### TestFX Usage
>>>>>>
>>>>>>                     ```java
>>>>>>                     @Override
>>>>>>                     public Image getCaptureRegion(Rectangle2D region) {
>>>>>>                         return waitForAsyncFx(RETRIEVAL_TIMEOUT_IN_MILLIS, () -> {
>>>>>>                             Pixels glassPixels = useRobot().getScreenCapture(
>>>>>>                                 (int) region.getMinX(), (int) region.getMinY(),
>>>>>>                                 (int) region.getWidth(), (int) region.getHeight()
>>>>>>                             );
>>>>>>                             return convertFromGlassPixels(glassPixels);
>>>>>>                         });
>>>>>>                     }
>>>>>>
>>>>>>                     private Image convertFromGlassPixels(Pixels glassPixels) {
>>>>>>                         int width = glassPixels.getWidth();
>>>>>>                         int height = glassPixels.getHeight();
>>>>>>                         WritableImage image = new WritableImage(width, height);
>>>>>>
>>>>>>                         int bytesPerComponent = glassPixels.getBytesPerComponent();
>>>>>>                         if (bytesPerComponent == INT_BUFFER_BYTES_PER_COMPONENT) {
>>>>>>                             IntBuffer intBuffer = (IntBuffer) glassPixels.getPixels();
>>>>>>                             writeIntBufferToImage(intBuffer, image);
>>>>>>                         }
>>>>>>
>>>>>>                         return image;
>>>>>>                     }
>>>>>>
>>>>>>                     private void writeIntBufferToImage(IntBuffer intBuffer,
>>>>>>                                                        WritableImage image) {
>>>>>>                         PixelWriter pixelWriter = image.getPixelWriter();
>>>>>>                         double width = image.getWidth();
>>>>>>                         double height = image.getHeight();
>>>>>>
>>>>>>                         for (int y = 0; y < height; y++) {
>>>>>>                             for (int x = 0; x < width; x++) {
>>>>>>                                 int argb = intBuffer.get();
>>>>>>                                 pixelWriter.setArgb(x, y, argb);
>>>>>>                             }
>>>>>>                         }
>>>>>>                     }
>>>>>>                     ```
>>>>>>
>>>>>>                     Pixels is used to create a screen capture.
>>>>>>
>>>>>>                     ##### Suggested Public API Replacement
>>>>>>
>>>>>>                     Bypass needing to expose the Pixels class to the public API by
>>>>>>                     changing the getScreenCapture method of Robot - that is, changing:
>>>>>>
>>>>>>                     `public Pixels getScreenCapture(int x, int y, int width, int height)`
>>>>>>
>>>>>>                     to:
>>>>>>
>>>>>>                     `public Image getScreenCapture(int x, int y, int width, int height)`
>>>>>>
>>>>>>                     #### com.sun.glass.ui.Robot
>>>>>>
>>>>>>                     ##### TestFX Usage
>>>>>>
>>>>>>                     Essentially every method of Robot is used:
>>>>>>
>>>>>>                     ```
>>>>>>                     public void keyPress(int code)
>>>>>>                     public void keyRelease(int code)
>>>>>>                     public int getMouseX()
>>>>>>                     public int getMouseY()
>>>>>>                     public void mouseMove(int x, int y)
>>>>>>                     public void mousePress(int buttons)
>>>>>>                     public void mouseRelease(int buttons)
>>>>>>                     public void mouseWheel(int wheelAmt)
>>>>>>                     public int getPixelColor(int x, int y)
>>>>>>                     public Pixels getScreenCapture(int x, int y, int width, int height)
>>>>>>                     ```
>>>>>>
>>>>>>                     ##### Suggested Public API Replacement
>>>>>>
>>>>>>                     https://github.com/brcolow/openjfx/blob/master/modules/javaf <https://github.com/brcolow/openjfx/blob/master/modules/javaf>
>>>>>>                     x.graphics/src/main/java/javafx/scene/robot/Robot.java
>>>>>>
>>>>>>
>>>>>>                     --
>>>>>>                     Michael Ennen
>>>>>>
>>>>>>                           
>>>>>                     --
>>>>>                     Michael Ennen
>>>>>
>>>>>                         
>>>>                       
>>>
>>>
>>>
>>>
>>>                 -- 
>>>                 Michael Ennen
>>>
>>>
>>>
>>>
>>>             -- 
>>>             Michael Ennen
>>
>>
>>
>>
>>         -- 
>>         Michael Ennen
>
>
>
>
>     -- 
>     Michael Ennen
>
>
>
>
> -- 
> Michael Ennen


More information about the openjfx-dev mailing list