Hi,
as promised here is the list of current private api usages of our application.
Any advice how to achieve the same with public apis is always welcome.
* We use com.sun.webkit.WebPage and com.sun.javafx.webkit.Accessor to implement
our own frontend for the html editor.
It seems to be unmaintained by oracle. Has anyone used an texteditor, where
it is not possible to do a line break
(https://javafx-jira.kenai.com/browse/RT-38412)? Bug was filed August 2014
and was deferred from 8u40 to 9.
The bug can only be tracked down by oracle, because the bug is probably in
the plugin code, which is still closed source.
Well we have a semi working workaround involving private apis...
Whatever we currently implement a new text editor based on TextFlow, because
the html editor is simply too buggy.
So for us this will no longer an issue with Java 9.
* com.sun.javafx.scene.control.skin.ComboBoxListViewSkin is used to scroll to
entry matching typed key in a ComboBoxListView
There is a feature request from 2011 for this:
https://javafx-jira.kenai.com/browse/RT-18064.
Perhaps its enough to expose scrollTo. That is
https://javafx-jira.kenai.com/browse/RT-34661.
fontFamilyComboBox.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (fontFamilyComboBox.isShowing()) {
@SuppressWarnings("rawtypes")
ListView cbListView =
((ComboBoxListViewSkin) fontFamilyComboBox.getSkin()).getListView();
String typed =
event.getCode().toString().toLowerCase();
ObservableList<String> fontList =
fontFamilyComboBox.getItems();
for (int i = 0; i < fontList.size();
i++) {
String font =
fontList.get(i).toLowerCase();
if (font.startsWith(typed)) {
fontFamilyComboBox.getSelectionModel().clearAndSelect(i);
cbListView.scrollTo(i);
break;
}
}
}
}
});
* We maximize our application window to full screen on startup with this code
This is a workaround for https://javafx-jira.kenai.com/browse/RT-32422
import com.sun.glass.ui.Window;
import com.sun.javafx.application.PlatformImpl;
if (!isEmbedded && Window.getFocusedWindow() != null) {
Logger.getLogger(getClass()).debug(Settings.getInstance().getBoolProperty("mainStageMaximized",
true));
try {
Window.getFocusedWindow().maximize(Settings.getInstance().getBoolProperty("mainStageMaximized",
true));
} catch (Exception e) {
// java.lang.IllegalStateException: The window has already
been closed on linux
}
Logger.getLogger(getClass()).info("maximized focused window " +
Window.getFocusedWindow().getTitle());
}
* ComboBoxes, we have the requirement to automatically open comboboxes on
mouseover. The combobox should not be closed on mouseclick:
Expose the value of isHideOnClickEnabled in our ExtendedComboBox control.
@Override
protected Skin<?> createDefaultSkin() {
Skin<?> s = new ComboBoxListViewSkin<T>(this){
@Override
protected boolean isHideOnClickEnabled() {
return getIsHideOnClickEnabled();
}
@Override
protected PopupControl getPopup() {
PopupControl p = super.getPopup();
p.autoHideProperty().bind(autoHideProperty);
return p;
}
};
return s;
}
* com.sun.glass.ui.Robot is used to work around a bug, that the Browser window
does not get focus after the SWT-Filedialog is closed on Mac
-> We would not have to use the SWT-Filedialog at all and could use the
JavaFX-Filedialog, ifhttps://javafx-jira.kenai.com/browse/RT-38809 was fixed.
Browser Mode: activate browser after swt-filedialog has been closed
if(EditorFX.getInstance().getHostServices().getWebContext()!=null) {
LOG.debug("disposeAll -> create Robot");
Robot robot =
com.sun.glass.ui.Application.GetApplication().createRobot();
if(robot!=null) {
robot.mousePress(1);
robot.mouseRelease(1);
robot.destroy();
LOG.debug("disposeAll -> Robot destroyed");
}
}
* com.sun.glass.ui.Robot is also used to get screen coordinates for checks, if
the mouse is over a node or not.
We found that mouseEntered and mouseExited events do not work reliable. E.g.:
mouseExited Events not triggered, mouseEntered are triggered before mouseExited
on previous node)
* Gather various information about the used hardware in case of an unhandled
exception.
In case of an unhandled exception we gather various information about the
affected computer and ask the user to upload it to us for further analysis.
Our dialog is similar to what Firefox
does:https://support.mozilla.org/en-US/kb/mozillacrashreporter
These are some of our hacks to get information about the current hardware used:
public static long getTotalPhysicalMemorySize() {
com.sun.management.OperatingSystemMXBean os =
(com.sun.management.OperatingSystemMXBean)
java.lang.management.ManagementFactory.getOperatingSystemMXBean();
return os.getTotalPhysicalMemorySize();
}
public static long getFreePhysicalMemorySize() {
com.sun.management.OperatingSystemMXBean os =
(com.sun.management.OperatingSystemMXBean)
java.lang.management.ManagementFactory.getOperatingSystemMXBean();
return os.getFreePhysicalMemorySize();
getWindowsGraphicCardInfo retrieves the same information, which would have been
logged by prism.verbose=true
public class WindowsHardwareInfo {
public static String getWindowsGraphicCardInfo() {
String info = "";
try {
// ResourceFactory resourceFactory =
D3DPipeline.getDefaultResourceFactory()
Class<?> d3DPipelineClass = (Class<?>)
Class.forName("com.sun.prism.d3d.D3DPipeline");
Method getDefaultResourceFactoryMethod =
d3DPipelineClass.getMethod("getDefaultResourceFactory");
ResourceFactory resourceFactory = (ResourceFactory)
getDefaultResourceFactoryMethod.invoke(null);
info += "Maximum texture size: " +
resourceFactory.getMaximumTextureSize() + "\n" ;
// int adapterCount = D3DPipeline.nGetAdapterCount()
Method nGetAdapterCountMethod =
d3DPipelineClass.getDeclaredMethod("nGetAdapterCount");
nGetAdapterCountMethod.setAccessible(true);
int adapterCount = (Integer)
nGetAdapterCountMethod.invoke(null);
Class<?> d3DDriverInformationClass = (Class<?>)
Class.forName("com.sun.prism.d3d.D3DDriverInformation");
Method nGetDriverInformationMethod =
d3DPipelineClass.getDeclaredMethod("nGetDriverInformation", int.class,
d3DDriverInformationClass );
nGetDriverInformationMethod.setAccessible(true);
Constructor<?> constructor =
d3DDriverInformationClass.getDeclaredConstructor();
constructor.setAccessible(true);
for (int adapter = 0, n = adapterCount; adapter != n;
++adapter) {
//D3DPipeline.nGetDriverInformation(adapter,
new D3DDriverInformation());
Object di =
nGetDriverInformationMethod.invoke(null, adapter, constructor.newInstance());
if (di != null) {
info += "Graphics adapter #" + adapter + "\n";
info += "OS Information:\n";
info += "\t" + callGetter(di, d3DDriverInformationClass, "getOsVersion") +
" build " + getField(di, d3DDriverInformationClass, "osBuildNumber") + "\n";
info += "D3D Driver Information:\n";
info += "\t" + getField(di, d3DDriverInformationClass,
"deviceDescription") + "\n";
info += "\t" + getField(di, d3DDriverInformationClass,
"deviceName") + "\n";
info += "\tDriver " + getField(di, d3DDriverInformationClass, "driverName") +
", version " + callGetter(di, d3DDriverInformationClass, "getDriverVersion") + "\n";
info += "\tPixel Shader version " + getField(di, d3DDriverInformationClass,
"psVersionMajor") + "." + getField(di, d3DDriverInformationClass, "psVersionMinor") +
"\n";
info += "\tDevice : " + callGetter(di, d3DDriverInformationClass,
"getDeviceID") + "\n";
// System.out.println("\tMax Multisamples supported: "
+ di.maxSamples);
Object warning = getField(di, d3DDriverInformationClass,
"warningMessage");
if (warning != null) {
info += "\t *** " + warning + "\n";
}
}
}
} catch (Exception e) {
info += "Unable to retrieve hardware info: " +
e.getMessage();
}
return info;
}
private static Object callGetter(Object object, Class<?> objectClass,
String methodName) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method method = objectClass.getDeclaredMethod(methodName);
method.setAccessible(true);
return method.invoke(object);
}
private static Object getField(Object object, Class<?> objectClass,
String fieldName) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
Field field = objectClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
}
For OutOfMemory exceptions, we create a heapdump file like this:
public static void dumpHeap(String fileName, boolean live) throws Exception
{
// initialize hotspot diagnostic MBean
Object hotspotMBean = getHotspotMBean();
Class<?> clazz =
Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
Method m = clazz.getMethod("dumpHeap", String.class, boolean.class);
m.invoke( hotspotMBean , fileName, live);
}
// get the hotspot diagnostic MBean from the
// platform MBean server
private static Object getHotspotMBean() throws ClassNotFoundException,
IOException {
Class<?> clazz =
Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
return ManagementFactory.newPlatformMXBeanProxy(server,
HOTSPOT_BEAN_NAME, clazz);
}
These are the current usages of private apis in our application.
However we include various other libraries, which I have not checked yet. Some
of them are no longer maintained.
So obviously for most of the problems there are open jiras, many of them years
old.
- Stefan
I' ll try to compile a list of the private apis we currently use in
our application and why.
Looking forward to using only public apis in java 9 then :-)
- Stefan
On Apr 8, 2015, at 1:52 PM, Robert Krüger <[email protected]> wrote:
our only workaround is to use private API
For the benefit of the devs on the list, could you please point out
what private APIs you currently need to use? That way we can make
sure proper JIRAs are filed and we can connect those to actual
real-world problems.