mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-08 09:31:42 +01:00
Compare commits
32 Commits
jb11_0_6-b
...
malenkov/f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d2f25483a | ||
|
|
f45f84d7ed | ||
|
|
06b0d02208 | ||
|
|
bc09aadadb | ||
|
|
dda7f3d871 | ||
|
|
7f025f4e16 | ||
|
|
1e904db3b0 | ||
|
|
c013b03300 | ||
|
|
08aa0852b7 | ||
|
|
23f2c1c42d | ||
|
|
53744bf65f | ||
|
|
430fdb17a8 | ||
|
|
b37fdd89bf | ||
|
|
e57bae4f66 | ||
|
|
0587074d61 | ||
|
|
a6e441828a | ||
|
|
cbb148dff4 | ||
|
|
1f4ab12fbb | ||
|
|
0f895bf1b2 | ||
|
|
05af375909 | ||
|
|
92606f2c7f | ||
|
|
2d587b3728 | ||
|
|
48468b08d0 | ||
|
|
31b590c16c | ||
|
|
78bdb2e198 | ||
|
|
c64c10cbf0 | ||
|
|
ae91e1d7f1 | ||
|
|
ca2209dd48 | ||
|
|
354855edc2 | ||
|
|
98087b0773 | ||
|
|
3dfb0aa16a | ||
|
|
18b9bf5b0b |
@@ -75,7 +75,7 @@ First command will set env vars, the second will run cygwin shell with proper en
|
||||
In cygwin shell
|
||||
```
|
||||
cd JetBrainsRuntime
|
||||
./configure --disable-warnings-as-errors
|
||||
bash configure --enable-option-checking=fatal --enable-option-checking=fatal --with-toolchain-version=2015 --with-boot-jdk="/cygdrive/c/Program Files/Java/jdk-11.0.5" --disable-warnings-as-errors
|
||||
make images
|
||||
```
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# jetbrains/runtime:jbr11env
|
||||
# jetbrains/runtime:jbr11dev8env
|
||||
FROM centos:7
|
||||
|
||||
RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool gcc gcc-c++ libstdc++-devel alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel
|
||||
RUN yum -y install centos-release-scl
|
||||
RUN yum -y install devtoolset-8
|
||||
RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel
|
||||
# Install Java 11
|
||||
RUN wget https://bintray.com/jetbrains/intellij-jbr/download_file?file_path=jbrsdk-11_0_3-linux-x64-b360.2.tar.gz \
|
||||
-O - | tar xz -C /
|
||||
ENV JAVA_HOME /jbrsdk
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
ENV PATH $JAVA_HOME/bin:/opt/rh/devtoolset-8/root/usr/bin:$PATH
|
||||
|
||||
@@ -495,7 +495,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/relocInfo_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/cpustate_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/immediate_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/vmreg_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp
|
||||
@@ -520,7 +519,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/decode_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/codeBuffer_aarch64.hpp
|
||||
@@ -529,7 +527,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/cpu/aarch64/assembler_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/register_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp
|
||||
../../../src/hotspot/cpu/aarch64/aarch64_call.cpp
|
||||
../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp
|
||||
../../../src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp
|
||||
@@ -1175,13 +1172,11 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolBuffer.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrChunkSizeNotifier.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrChunkState.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrRepository.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrChunkSizeNotifier.cpp
|
||||
../../../src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
|
||||
../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointBlob.hpp
|
||||
../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp
|
||||
@@ -1254,7 +1249,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/emitEventOperation.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSample.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/sampling/sampleList.cpp
|
||||
@@ -1270,7 +1264,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/utilities/unifiedOop.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/startOperation.hpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/emitEventOperation.cpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp
|
||||
../../../src/hotspot/share/jfr/leakprofiler/chains/edge.hpp
|
||||
@@ -1481,7 +1474,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/runtime/basicLock.hpp
|
||||
../../../src/hotspot/share/runtime/compilationPolicy.cpp
|
||||
../../../src/hotspot/share/runtime/java.hpp
|
||||
../../../src/hotspot/share/runtime/simpleThresholdPolicy.cpp
|
||||
../../../src/hotspot/share/runtime/objectMonitor.inline.hpp
|
||||
../../../src/hotspot/share/runtime/mutexLocker.cpp
|
||||
../../../src/hotspot/share/runtime/serviceThread.cpp
|
||||
@@ -1524,7 +1516,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/runtime/compilationPolicy.hpp
|
||||
../../../src/hotspot/share/runtime/basicLock.cpp
|
||||
../../../src/hotspot/share/runtime/java.cpp
|
||||
../../../src/hotspot/share/runtime/simpleThresholdPolicy.hpp
|
||||
../../../src/hotspot/share/runtime/perfData.inline.hpp
|
||||
../../../src/hotspot/share/runtime/statSampler.hpp
|
||||
../../../src/hotspot/share/runtime/vm_operations.cpp
|
||||
@@ -1557,7 +1548,6 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/runtime/handshake.hpp
|
||||
../../../src/hotspot/share/runtime/thread.inline.hpp
|
||||
../../../src/hotspot/share/runtime/perfMemory.hpp
|
||||
../../../src/hotspot/share/runtime/simpleThresholdPolicy.inline.hpp
|
||||
../../../src/hotspot/share/runtime/javaCalls.cpp
|
||||
../../../src/hotspot/share/runtime/reflection.cpp
|
||||
../../../src/hotspot/share/runtime/icache.cpp
|
||||
|
||||
@@ -1088,7 +1088,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.h
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsConfig.m
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/PrintModel.h
|
||||
../../../src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m
|
||||
@@ -1342,7 +1341,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux"
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/multi_font.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/multiVis.h
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/awt_Event.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/robot_common.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/list.h
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h
|
||||
@@ -1355,7 +1353,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux"
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/canvas.h
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/awt_AWTEvent.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/multi_font.h
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/robot_common.h
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
|
||||
../../../src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
|
||||
|
||||
@@ -72,6 +72,17 @@ else
|
||||
BUILD_JDK_JTREG_EXCLUDE += libTestMainKeyWindow.c
|
||||
endif
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
BUILD_JDK_JTREG_LIBRARIES_LIBS_libwindows_touch_robot := user32.lib
|
||||
BUILD_JDK_JTREG_EXCLUDE += libtouchscreen_device.c
|
||||
else
|
||||
ifeq ($(OPENJDK_TARGET_OS), linux)
|
||||
BUILD_JDK_JTREG_EXCLUDE += libwindows_touch_robot.c
|
||||
else
|
||||
BUILD_JDK_JTREG_EXCLUDE += libtouchscreen_device.c libwindows_touch_robot.c
|
||||
endif
|
||||
endif
|
||||
|
||||
$(eval $(call SetupTestFilesCompilation, BUILD_JDK_JTREG_LIBRARIES, \
|
||||
TYPE := LIBRARY, \
|
||||
SOURCE_DIRS := $(BUILD_JDK_JTREG_NATIVE_SRC), \
|
||||
|
||||
@@ -27,7 +27,6 @@ package sun.font;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
@@ -41,6 +40,7 @@ import javax.swing.plaf.FontUIResource;
|
||||
import sun.awt.FontConfiguration;
|
||||
import sun.awt.HeadlessToolkit;
|
||||
import sun.lwawt.macosx.*;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public final class CFontManager extends SunFontManager {
|
||||
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
|
||||
@@ -144,10 +144,39 @@ public final class CFontManager extends SunFontManager {
|
||||
protected void registerJREFonts() {
|
||||
String[] files = AccessController.doPrivileged((PrivilegedAction<String[]>) () ->
|
||||
new File(jreFontDirName).list(getTrueTypeFilter()));
|
||||
|
||||
if (files != null) {
|
||||
PlatformLogger logger = FontUtilities.getLogger();
|
||||
int [] ver = new int[3];
|
||||
for (String f : files) {
|
||||
loadNativeDirFonts(jreFontDirName + File.separator + f);
|
||||
boolean loadFont = true;
|
||||
BundledFontInfo fi = getBundledFontInfo(f);
|
||||
if (versionCheckEnabled) {
|
||||
if (fi != null) {
|
||||
String verStr = getNativeFontVersion(fi.getPsName());
|
||||
if (logger != null) {
|
||||
logger.info("Checking bundled " + fi.getPsName());
|
||||
}
|
||||
if (verStr != null && parseFontVersion(verStr, ver) && !fi.isNewerThan(ver)) {
|
||||
if (logger != null) {
|
||||
logger.info("Skip loading. Newer or same version platform font detected " +
|
||||
fi.getPsName() + " " + verStr);
|
||||
}
|
||||
loadFont = false;
|
||||
}
|
||||
} else {
|
||||
if (logger != null) {
|
||||
FontUtilities.getLogger().warning("JREFonts: No BundledFontInfo for : " + f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loadFont) {
|
||||
String fontPath = jreFontDirName + File.separator + f;
|
||||
loadNativeDirFonts(fontPath);
|
||||
if (logger != null && fi != null) {
|
||||
String verStr = getNativeFontVersion(fi.getPsName());
|
||||
logger.info("Loaded " + fi.getPsName() + " (" + verStr + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,6 +200,7 @@ public final class CFontManager extends SunFontManager {
|
||||
|
||||
private native void loadNativeDirFonts(String fontPath);
|
||||
private native void loadNativeFonts();
|
||||
native String getNativeFontVersion(String psName);
|
||||
|
||||
void registerFont(String fontName, String fontFamilyName) {
|
||||
// Use different family for specific font faces
|
||||
|
||||
@@ -63,7 +63,7 @@ import com.apple.laf.ClientPropertyApplicator.Property;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.awt.AWTAccessor.WindowAccessor;
|
||||
import sun.awt.InvokeOnToolkitHelper;
|
||||
import sun.awt.AWTThreading;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.opengl.CGLSurfaceData;
|
||||
import sun.lwawt.LWLightweightFramePeer;
|
||||
@@ -331,7 +331,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
long nativeWindowPtr = java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<Long>) () -> {
|
||||
try {
|
||||
return InvokeOnToolkitHelper.invokeAndBlock(() -> {
|
||||
return AWTThreading.executeWaitToolkit(() -> {
|
||||
AtomicLong ref = new AtomicLong();
|
||||
contentView.execute(viewPtr -> {
|
||||
boolean hasOwnerPtr = false;
|
||||
|
||||
@@ -472,7 +472,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
public Insets getScreenInsets(final GraphicsConfiguration gc) {
|
||||
CGraphicsDevice gd = ((CGraphicsConfig) gc).getDevice();
|
||||
// Avoid deadlock with input methods
|
||||
return InvokeOnToolkitHelper.invokeAndBlock(gd::getScreenInsets);
|
||||
return AWTThreading.executeWaitToolkit(gd::getScreenInsets);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -726,7 +726,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
final long mediator = createAWTRunLoopMediator();
|
||||
|
||||
InvocationEvent invocationEvent =
|
||||
new InvocationEvent(component,
|
||||
AWTThreading.createAndTrackInvocationEvent(component,
|
||||
runnable,
|
||||
() -> {
|
||||
if (mediator != 0) {
|
||||
@@ -735,17 +735,16 @@ public final class LWCToolkit extends LWToolkit {
|
||||
},
|
||||
true);
|
||||
|
||||
if (!InvokeOnToolkitHelper.offer(invocationEvent)) {
|
||||
if (component != null) {
|
||||
AppContext appContext = SunToolkit.targetToAppContext(component);
|
||||
SunToolkit.postEvent(appContext, invocationEvent);
|
||||
if (component != null) {
|
||||
AppContext appContext = SunToolkit.targetToAppContext(component);
|
||||
SunToolkit.postEvent(appContext, invocationEvent);
|
||||
|
||||
// 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock
|
||||
SunToolkit.flushPendingEvents(appContext);
|
||||
} else {
|
||||
// This should be the equivalent to EventQueue.invokeAndWait
|
||||
((LWCToolkit) Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
|
||||
}
|
||||
// 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock
|
||||
SunToolkit.flushPendingEvents(appContext);
|
||||
}
|
||||
else {
|
||||
// This should be the equivalent to EventQueue.invokeAndWait
|
||||
((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
|
||||
}
|
||||
|
||||
doAWTRunLoop(mediator, nonBlockingRunLoop);
|
||||
|
||||
@@ -1402,6 +1402,41 @@ JNF_COCOA_ENTER(env);
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: Java_sun_font_CFontManager_loadNativeDirFonts
|
||||
* Method: getNativeFontVersion
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT JNICALL jstring
|
||||
Java_sun_font_CFontManager_getNativeFontVersion
|
||||
(JNIEnv *env, jclass clz, jstring psName)
|
||||
{
|
||||
jstring result = NULL;
|
||||
JNF_COCOA_ENTER(env);
|
||||
NSString *psNameStr = JNFJavaToNSString(env, psName);
|
||||
CTFontRef sFont = CTFontCreateWithName(psNameStr, 13, nil);
|
||||
if (sFont != NULL) {
|
||||
CFStringRef sFontPSName = CTFontCopyName(sFont, kCTFontPostScriptNameKey);
|
||||
|
||||
// CTFontCreateWithName always returns some font,
|
||||
// so we need to check if it is right one
|
||||
if (sFontPSName != NULL && [psNameStr isEqualToString:sFontPSName]) {
|
||||
CFStringRef fontVersionStr = CTFontCopyName(sFont,
|
||||
kCTFontVersionNameKey);
|
||||
if (fontVersionStr != NULL) {
|
||||
result = JNFNSToJavaString(env, fontVersionStr);
|
||||
CFRelease(fontVersionStr);
|
||||
}
|
||||
}
|
||||
if (sFontPSName != NULL) {
|
||||
CFRelease(sFontPSName);
|
||||
}
|
||||
CFRelease(sFont);
|
||||
}
|
||||
JNF_COCOA_EXIT(env);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: Java_sun_font_CFontManager_loadNativeDirFonts
|
||||
* Method: loadNativeDirFonts
|
||||
|
||||
@@ -375,6 +375,7 @@ public abstract class JComponent extends Container implements Serializable,
|
||||
* AA text hints.
|
||||
*/
|
||||
private transient Object aaHint;
|
||||
private transient Object fmHint;
|
||||
private transient Object lcdRenderingHint;
|
||||
|
||||
static {
|
||||
@@ -677,6 +678,8 @@ public abstract class JComponent extends Container implements Serializable,
|
||||
// aaText shouldn't persist between look and feels, reset it.
|
||||
aaHint = UIManager.getDefaults().get(
|
||||
RenderingHints.KEY_TEXT_ANTIALIASING);
|
||||
fmHint = UIManager.getDefaults().get(
|
||||
RenderingHints.KEY_FRACTIONALMETRICS);
|
||||
lcdRenderingHint = UIManager.getDefaults().get(
|
||||
RenderingHints.KEY_TEXT_LCD_CONTRAST);
|
||||
ComponentUI oldUI = ui;
|
||||
@@ -4047,6 +4050,8 @@ public abstract class JComponent extends Container implements Serializable,
|
||||
public final Object getClientProperty(Object key) {
|
||||
if (key == RenderingHints.KEY_TEXT_ANTIALIASING) {
|
||||
return aaHint;
|
||||
} else if (key == RenderingHints.KEY_FRACTIONALMETRICS) {
|
||||
return fmHint;
|
||||
} else if (key == RenderingHints.KEY_TEXT_LCD_CONTRAST) {
|
||||
return lcdRenderingHint;
|
||||
}
|
||||
@@ -4091,6 +4096,9 @@ public abstract class JComponent extends Container implements Serializable,
|
||||
if (key == RenderingHints.KEY_TEXT_ANTIALIASING) {
|
||||
aaHint = value;
|
||||
return;
|
||||
} else if (key == RenderingHints.KEY_FRACTIONALMETRICS) {
|
||||
fmHint = value;
|
||||
return;
|
||||
} else if (key == RenderingHints.KEY_TEXT_LCD_CONTRAST) {
|
||||
lcdRenderingHint = value;
|
||||
return;
|
||||
|
||||
207
src/java.desktop/share/classes/sun/awt/AWTThreading.java
Normal file
207
src/java.desktop/share/classes/sun/awt/AWTThreading.java
Normal file
@@ -0,0 +1,207 @@
|
||||
package sun.awt;
|
||||
|
||||
import sun.font.FontUtilities;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Used to perform a cross threads (EventDispatch, Toolkit) execution so that the execution does not cause a deadlock.
|
||||
*/
|
||||
public class AWTThreading {
|
||||
private ExecutorService executor;
|
||||
// every invokeAndWait() pushes a queue of invocations
|
||||
private final Stack<TrackingQueue> invocations = new Stack<>();
|
||||
|
||||
private int level; // re-entrance level
|
||||
|
||||
// invocations should be dispatched on proper EDT (per AppContext)
|
||||
private static final Map<Thread, AWTThreading> EDT_TO_INSTANCE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private static class TrackingQueue extends LinkedBlockingQueue<InvocationEvent> {}
|
||||
|
||||
private AWTThreading() {}
|
||||
|
||||
/**
|
||||
* Executes a callable from EventDispatch thread (EDT). It's assumed the callable either performs a blocking execution on Toolkit
|
||||
* or waits a notification from Toolkit. The method is re-entrant.
|
||||
* <p>
|
||||
* Currently only macOS is supported. The callable can wrap a native obj-c selector. The selector should be executed via
|
||||
* [JNFRunLoop performOnMainThreadWaiting:YES ...] so that doAWTRunLoop on AppKit (which is run in [JNFRunLoop javaRunLoopMode]) accepts it.
|
||||
* The callable should not call any Java code that would normally be called on EDT.
|
||||
* <p>
|
||||
* A deadlock can happen when the callable triggers any blocking invocation from Toolkit to EDT, or when Toolkit already waits in
|
||||
* such blocking invocation. To avoid that:
|
||||
* <ul>
|
||||
* <li>The callback execution is delegated to a dedicated pool thread.
|
||||
* <li>All invocation events, initiated by Toolkit via invokeAndWait(), are tracked via a dedicated queue.
|
||||
* <li>All the tracked invocation events are dispatched on EDT out of order (EventQueue) during the callback execution.
|
||||
* <li>In case of a re-entrant method call, all the tracked invocation events coming after the call are dispatched first.
|
||||
* </ul><p>
|
||||
* When called on non-EDT, or on non-macOS, the method executes the callable just in place.
|
||||
*/
|
||||
public static <T> T executeWaitToolkit(Callable<T> callable) {
|
||||
return executeWaitToolkit(callable, -1, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #executeWaitToolkit(Callable)} except that the method waits no longer than the specified timeout.
|
||||
*/
|
||||
public static <T> T executeWaitToolkit(Callable<T> callable, long timeout, TimeUnit unit) {
|
||||
if (callable == null) return null;
|
||||
|
||||
if (FontUtilities.isMacOSX && EventQueue.isDispatchThread()) {
|
||||
AWTThreading instance = getInstance(Thread.currentThread());
|
||||
if (instance != null) {
|
||||
return instance.execute(callable, timeout, unit);
|
||||
}
|
||||
}
|
||||
// fallback to default
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private <T> T execute(Callable<T> callable, long timeout, TimeUnit unit) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
if (executor == null) {
|
||||
// init on EDT
|
||||
AccessController.doPrivileged((PrivilegedAction<?>)() ->
|
||||
executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<>(),
|
||||
new ThreadFactory() {
|
||||
private final ThreadFactory factory = Executors.privilegedThreadFactory();
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = factory.newThread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("AWT-" + AWTThreading.class.getSimpleName() + " " + t.getName());
|
||||
return t;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
level++;
|
||||
try {
|
||||
TrackingQueue currentQueue;
|
||||
synchronized (invocations) {
|
||||
if (level == 1 && invocations.size() == 1) {
|
||||
currentQueue = invocations.peek();
|
||||
} else {
|
||||
invocations.push(currentQueue = new TrackingQueue());
|
||||
}
|
||||
}
|
||||
|
||||
FutureTask<T> task = new FutureTask<>(callable) {
|
||||
@Override
|
||||
protected void done() {
|
||||
synchronized (invocations) {
|
||||
invocations.remove(currentQueue);
|
||||
// add dummy event to wake up the queue
|
||||
currentQueue.add(new InvocationEvent(new Object(), () -> {}));
|
||||
}
|
||||
}
|
||||
};
|
||||
executor.execute(task);
|
||||
|
||||
try {
|
||||
while (!task.isDone() || !currentQueue.isEmpty()) {
|
||||
InvocationEvent event;
|
||||
if (timeout >= 0 && unit != null) {
|
||||
event = currentQueue.poll(timeout, unit);
|
||||
} else {
|
||||
event = currentQueue.take();
|
||||
}
|
||||
if (event == null) {
|
||||
task.cancel(false);
|
||||
synchronized (invocations) {
|
||||
invocations.remove(currentQueue);
|
||||
}
|
||||
new RuntimeException("Waiting for the invocation event timed out").printStackTrace();
|
||||
break;
|
||||
}
|
||||
event.dispatch();
|
||||
}
|
||||
return task.isCancelled() ? null : task.get();
|
||||
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
level--;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by implementation.
|
||||
* Creates an invocation event and adds it to the tracking queue.
|
||||
* It's assumed the event is then posted to EventQueue.
|
||||
* The following is provided:
|
||||
* <ul>
|
||||
* <li>If the event is first dispatched from EventQueue - it gets removed from the tracking queue.
|
||||
* <li>If the event is first dispatched from the tracking queue - its dispatching on EventQueue will be noop.
|
||||
* <ul>
|
||||
*/
|
||||
public static InvocationEvent createAndTrackInvocationEvent(Object source, Runnable runnable, Runnable listener, boolean catchThrowables) {
|
||||
AWTThreading instance = getInstance(source);
|
||||
if (instance != null) {
|
||||
synchronized (instance.invocations) {
|
||||
if (instance.invocations.isEmpty()) {
|
||||
instance.invocations.push(new TrackingQueue());
|
||||
}
|
||||
final TrackingQueue queue = instance.invocations.peek();
|
||||
InvocationEvent event = new InvocationEvent(source, runnable, listener, catchThrowables) {
|
||||
final SoftReference<TrackingQueue> queueRef = new SoftReference<>(queue);
|
||||
|
||||
@Override
|
||||
public void dispatch() {
|
||||
if (!isDispatched()) {
|
||||
super.dispatch();
|
||||
|
||||
TrackingQueue queue = queueRef.get();
|
||||
if (queue != null) {
|
||||
queue.remove(this);
|
||||
queueRef.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
queue.add(event);
|
||||
return event;
|
||||
}
|
||||
}
|
||||
return new InvocationEvent(source, runnable, listener, catchThrowables);
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(Object obj) {
|
||||
if (obj == null) return null;
|
||||
|
||||
AppContext appContext = SunToolkit.targetToAppContext(obj);
|
||||
if (appContext == null) return null;
|
||||
|
||||
return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY));
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(EventQueue eq) {
|
||||
if (eq == null) return null;
|
||||
|
||||
return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq));
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(Thread edt) {
|
||||
if (edt == null) return null;
|
||||
|
||||
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> new AWTThreading());
|
||||
}
|
||||
}
|
||||
@@ -1,157 +1,15 @@
|
||||
package sun.awt;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Used to perform a blocking invocation on Toolkit thread from EDT, preventing a deadlock.
|
||||
* The deadlock can happen when EDT and Toolkit perform blocking invocations at the same time.
|
||||
* The following is performed to resolve it:
|
||||
* 1) The invoker spins a nested event loop on EDT while waiting for the invocation to complete.
|
||||
* 2) A separate pool thread is used to perform the invocation.
|
||||
* TODO: remove it in JBR 202
|
||||
*
|
||||
* @deprecated
|
||||
* @see AWTThreading
|
||||
*/
|
||||
public class InvokeOnToolkitHelper {
|
||||
private ExecutorService executor;
|
||||
// every invokeAndWait() pushes a queue of invocations
|
||||
private final Stack<LinkedBlockingQueue<InvocationEvent>> invocations = new Stack<>();
|
||||
|
||||
// invocations should be dispatched on proper EDT (per AppContext)
|
||||
private static final Map<Thread, InvokeOnToolkitHelper> edt2invokerMap = new ConcurrentHashMap<>();
|
||||
|
||||
private static final int WAIT_LIMIT_SECONDS = 5;
|
||||
|
||||
private InvokeOnToolkitHelper() {}
|
||||
|
||||
/**
|
||||
* Invokes the callable on Toolkit thread and blocks until the completion. The method is re-entrant.
|
||||
*
|
||||
* On macOS it is assumed the callable wraps a native selector. The selector should be executed via [JNFRunLoop performOnMainThreadWaiting:YES ...]
|
||||
* so that the doAWTRunLoop on AppKit (which is run in [JNFRunLoop javaRunLoopMode]) accepts it. The callable wrapper should not call any Java code
|
||||
* which would normally be called on EDT.
|
||||
* <p>
|
||||
* If Toolkit posts invocation events caused by the callable, those events are intercepted and dispatched on EDT out of order.
|
||||
* <p>
|
||||
* When called on non-EDT, the method invokes the callable in place.
|
||||
*/
|
||||
public static <T> T invokeAndBlock(Callable<T> callable) {
|
||||
if (callable == null) return null;
|
||||
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
InvokeOnToolkitHelper invoker = getInstance(Thread.currentThread());
|
||||
if (invoker != null) {
|
||||
return invoker.invoke(callable);
|
||||
}
|
||||
}
|
||||
// fallback to default
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private <T> T invoke(Callable<T> callable) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
if (executor == null) {
|
||||
// init on EDT
|
||||
AccessController.doPrivileged((PrivilegedAction<?>)() ->
|
||||
executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<>(),
|
||||
new ThreadFactory() {
|
||||
private final ThreadFactory factory = Executors.privilegedThreadFactory();
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = factory.newThread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("AWT-InvokeOnToolkitHelper " + t.getName());
|
||||
return t;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
LinkedBlockingQueue<InvocationEvent> currentQueue;
|
||||
synchronized (invocations) {
|
||||
invocations.push(currentQueue = new LinkedBlockingQueue<>());
|
||||
}
|
||||
|
||||
FutureTask<T> task = new FutureTask<T>(callable) {
|
||||
@Override
|
||||
protected void done() {
|
||||
synchronized (invocations) {
|
||||
// Done with the current queue, wake it up.
|
||||
invocations.pop().add(new InvocationEvent(executor, () -> {}));
|
||||
}
|
||||
}
|
||||
};
|
||||
executor.execute(task);
|
||||
|
||||
try {
|
||||
while (!task.isDone() || !currentQueue.isEmpty()) {
|
||||
InvocationEvent event = currentQueue.poll(WAIT_LIMIT_SECONDS, TimeUnit.SECONDS);
|
||||
if (event == null) {
|
||||
new RuntimeException("Waiting for the invocation event timed out").printStackTrace();
|
||||
break;
|
||||
}
|
||||
event.dispatch();
|
||||
}
|
||||
return task.isDone() ? task.get() : null;
|
||||
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning: the method is used by the implementation and should not be used by a client.
|
||||
*
|
||||
* Checks if there's an active InvokeOnToolkitHelper corresponding to the invocation's AppContext,
|
||||
* adds the invocation to the InvokeOnToolkitHelper's queue and returns true.
|
||||
* Otherwise does nothing and returns false.
|
||||
*/
|
||||
public static boolean offer(InvocationEvent invocation) {
|
||||
Object source = invocation.getSource();
|
||||
|
||||
InvokeOnToolkitHelper invoker = (source instanceof Component) ?
|
||||
getInstance((Component)source) :
|
||||
getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
|
||||
|
||||
if (invoker == null) return false;
|
||||
|
||||
synchronized (invoker.invocations) {
|
||||
if (!invoker.invocations.isEmpty()) {
|
||||
invoker.invocations.peek().add(invocation);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static InvokeOnToolkitHelper getInstance(Component comp) {
|
||||
if (comp == null) return null;
|
||||
|
||||
AppContext appContext = SunToolkit.targetToAppContext(comp);
|
||||
if (appContext == null) return null;
|
||||
|
||||
return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY));
|
||||
}
|
||||
|
||||
private static InvokeOnToolkitHelper getInstance(EventQueue eq) {
|
||||
if (eq == null) return null;
|
||||
|
||||
return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq));
|
||||
}
|
||||
|
||||
private static InvokeOnToolkitHelper getInstance(Thread edt) {
|
||||
if (edt == null) return null;
|
||||
|
||||
return edt2invokerMap.computeIfAbsent(edt, key -> new InvokeOnToolkitHelper());
|
||||
return AWTThreading.executeWaitToolkit(callable);
|
||||
}
|
||||
}
|
||||
|
||||
21
src/java.desktop/share/classes/sun/awt/event/TouchEvent.java
Normal file
21
src/java.desktop/share/classes/sun/awt/event/TouchEvent.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package sun.awt.event;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
public class TouchEvent {
|
||||
@Native public static final int TOUCH_BEGIN = 2;
|
||||
@Native public static final int TOUCH_UPDATE = 3;
|
||||
@Native public static final int TOUCH_END = 4;
|
||||
|
||||
/**
|
||||
* The allowable difference between coordinates of touch update events
|
||||
* in pixels
|
||||
*/
|
||||
@Native public static final int CLICK_RADIUS = 10;
|
||||
|
||||
/**
|
||||
* Stop owning touch processing after timeout
|
||||
* in ms
|
||||
*/
|
||||
public static final long NO_UPDATE_TIMEOUT = 1000L;
|
||||
}
|
||||
@@ -111,10 +111,6 @@ public abstract class FileFont extends PhysicalFont {
|
||||
return 1; // DEFAULT_CHARSET
|
||||
}
|
||||
|
||||
int getFontDataSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the public interface. The subclasses need to implement
|
||||
* this. The returned block may be longer than the requested length.
|
||||
|
||||
@@ -442,12 +442,8 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
}
|
||||
if (ptr == 0) {
|
||||
boolean fm = desc.fmHint == INTVAL_FRACTIONALMETRICS_ON;
|
||||
ptr = _getGlyphImageFromWindows(family, style, size, glyphCode, fm, rotation, charset,
|
||||
fileFont.getFontDataSize());
|
||||
if (ptr == 0 && FontUtilities.isLogging()) {
|
||||
FontUtilities.getLogger().warning("Failed to render glyph via GDI: code=" + glyphCode
|
||||
+ ", fontFamily=" + family + ", style=" + style + ", size=" + size + ", rotation=" + rotation);
|
||||
}
|
||||
ptr = _getGlyphImageFromWindows(family, style, size, glyphCode, fm,
|
||||
rotation, charset, ((TrueTypeFont)fileFont).fontDataSize);
|
||||
if (ptr != 0 && fm) {
|
||||
Point2D.Float metrics = new Point2D.Float();
|
||||
fileFont.getGlyphMetrics(pScalerContext, glyphCode, metrics);
|
||||
@@ -456,6 +452,12 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
}
|
||||
}
|
||||
if (ptr == 0) {
|
||||
if (FontUtilities.isLogging()) {
|
||||
FontUtilities.getLogger().warning(
|
||||
"Failed to render glyph using GDI: code=" + glyphCode
|
||||
+ ", fontFamily=" + family + ", style=" + style
|
||||
+ ", size=" + size);
|
||||
}
|
||||
ptr = fileFont.getGlyphImage(pScalerContext, glyphCode);
|
||||
}
|
||||
return ptr;
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class FontUtilities {
|
||||
* where the caller interprets 'layout' to mean any case where
|
||||
* one 'char' (ie the java type char) does not map to one glyph
|
||||
*/
|
||||
public static final int MAX_LAYOUT_CHARCODE = 0x206F;
|
||||
public static final int MAX_LAYOUT_CHARCODE = 0x20F0;
|
||||
|
||||
/**
|
||||
* Calls the private getFont2D() method in java.awt.Font objects.
|
||||
@@ -299,6 +299,9 @@ public final class FontUtilities {
|
||||
else if (code >= 0x206a && code <= 0x206f) { // directional control
|
||||
return true;
|
||||
}
|
||||
else if (code >= 0x20d0) { // U+20D0 - U+20D0 combining diacritical marks for symbols
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,38 @@ import sun.util.logging.PlatformLogger;
|
||||
* methods that have to be implemented by specific implementations.
|
||||
*/
|
||||
public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
protected static class BundledFontInfo {
|
||||
private String psName;
|
||||
private int [] version;
|
||||
|
||||
public BundledFontInfo(String psName, int major, int minor, int bugfix) {
|
||||
this.psName = psName;
|
||||
version = new int[3];
|
||||
version[0] = major;
|
||||
version[1] = minor;
|
||||
version[2] = bugfix;
|
||||
}
|
||||
|
||||
public String getPsName() {
|
||||
return psName;
|
||||
}
|
||||
|
||||
public boolean isNewerThan(int[] version) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (this.version[i] < version[i]) {
|
||||
return false;
|
||||
} else if (this.version[i] > version[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return psName + " v" + version[0] + "." + version[1] + "." + version[2];
|
||||
}
|
||||
}
|
||||
|
||||
private static class TTFilter implements FilenameFilter {
|
||||
public boolean accept(File dir,String name) {
|
||||
@@ -187,7 +219,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
private boolean loaded1dot0Fonts = false;
|
||||
boolean loadedAllFonts = false;
|
||||
boolean loadedAllFontFiles = false;
|
||||
private HashMap<String,String> jreFontMap;
|
||||
private HashMap<String,BundledFontInfo> jreFontMap;
|
||||
private HashSet<String> jreBundledFontFiles;
|
||||
HashMap<String,String> jreFamilyMap;
|
||||
String[] jreOtherFontFiles;
|
||||
@@ -230,6 +262,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
private Locale lastDefaultLocale;
|
||||
|
||||
public static boolean noType1Font;
|
||||
public static boolean versionCheckEnabled;
|
||||
|
||||
/* Used to indicate required return type from toArray(..); */
|
||||
private static String[] STR_ARRAY = new String[0];
|
||||
@@ -279,60 +312,55 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
* are rarely used. Consider removing the other mappings if there's
|
||||
* no evidence they are useful in practice.
|
||||
*/
|
||||
jreFontMap = new HashMap<String, String>();
|
||||
jreFontMap = new HashMap<>();
|
||||
jreBundledFontFiles = new HashSet<String>();
|
||||
jreFamilyMap = new HashMap<>();
|
||||
|
||||
/* Droid Sans Mono Family */
|
||||
jreFontMap.put("droid sans0", "DroidSans.ttf");
|
||||
jreFontMap.put("droid sans1", "DroidSans-Bold.ttf");
|
||||
jreFontMap.put("droid sans bold1", "DroidSans-Bold.ttf");
|
||||
jreFontMap.put("DroidSans.ttf", new BundledFontInfo("DroidSans", 1, 0, 0));
|
||||
jreFontMap.put("DroidSans-Bold.ttf", new BundledFontInfo("DroidSans-Bold", 1, 0, 0));
|
||||
|
||||
/* Droid Sans Mono Family */
|
||||
jreFontMap.put("droid sans mono0", "DroidSansMono.ttf");
|
||||
jreFontMap.put("droid sans mono slashed0",
|
||||
"DroidSansMonoSlashed.ttf");
|
||||
jreFontMap.put("droid sans mono dotted0",
|
||||
"DroidSansMonoDotted.ttf");
|
||||
jreFontMap.put("DroidSansMono.ttf", new BundledFontInfo("DroidSansMono", 1, 0, 0));
|
||||
jreFontMap.put("DroidSansMonoSlashed.ttf", new BundledFontInfo("DroidSansMonoSlashed", 1, 0, 0));
|
||||
jreFontMap.put("DroidSansMonoDotted.ttf", new BundledFontInfo("DroidSansMonoDotted", 1, 0, 0));
|
||||
|
||||
/* Droid Serif Family */
|
||||
jreFontMap.put("droid serif0", "DroidSerif-Regular.ttf");
|
||||
jreFontMap.put("droid serif1", "DroidSerif-Bold.ttf");
|
||||
jreFontMap.put("droid serif2", "DroidSerif-Italic.ttf");
|
||||
jreFontMap.put("droid serif3", "DroidSerif-BoldItalic.ttf");
|
||||
jreFontMap.put("droid serif bold1", "DroidSerif-Bold.ttf");
|
||||
jreFontMap.put("droid serif bold italic3", "DroidSerif-BoldItalic.ttf");
|
||||
jreFontMap.put("DroidSerif-Regular.ttf", new BundledFontInfo("DroidSerif", 1, 0, 0));
|
||||
jreFontMap.put("DroidSerif-Bold.ttf", new BundledFontInfo("DroidSerif-Bold", 1, 0, 0));
|
||||
jreFontMap.put("DroidSerif-Italic.ttf", new BundledFontInfo("DroidSerif-Italic", 1, 0, 0));
|
||||
jreFontMap.put("DroidSerif-BoldItalic.ttf", new BundledFontInfo("DroidSerif-BoldItalic", 1, 0, 0));
|
||||
|
||||
/* Idea bundled fonts */
|
||||
jreFontMap.put("FiraCode bold", "FiraCode-Bold.ttf");
|
||||
jreFontMap.put("FiraCode light", "FiraCode-Light.ttf");
|
||||
jreFontMap.put("FiraCode medium", "FiraCode-Medium.ttf");
|
||||
jreFontMap.put("FiraCode retina", "FiraCode-Retina.ttf");
|
||||
jreFontMap.put("FiraCode regular", "FiraCode-Regular.ttf");
|
||||
jreFontMap.put("FiraCode-Bold.ttf", new BundledFontInfo("FiraCode-Bold", 1, 206, 0));
|
||||
jreFontMap.put("FiraCode-Light.ttf", new BundledFontInfo("FiraCode-Light", 1, 206, 0));
|
||||
jreFontMap.put("FiraCode-Medium.ttf", new BundledFontInfo("FiraCode-Medium", 1, 206, 0));
|
||||
jreFontMap.put("FiraCode-Retina.ttf", new BundledFontInfo("FiraCode-Retina", 1, 206, 0));
|
||||
jreFontMap.put("FiraCode-Regular.ttf", new BundledFontInfo("FiraCode-Regular", 1, 206, 0));
|
||||
|
||||
jreFamilyMap.put("FiraCode-Medium", "Fira Code Medium");
|
||||
jreFamilyMap.put("FiraCode-Retina", "Fira Code Retina");
|
||||
jreFamilyMap.put("FiraCode-Light", "Fira Code Light");
|
||||
|
||||
jreFontMap.put("SourceCodePro bold italic", "SourceCodePro-BoldIt.ttf");
|
||||
jreFontMap.put("SourceCodePro regular", "SourceCodePro-Regular.ttf");
|
||||
jreFontMap.put("SourceCodePro bold", "SourceCodePro-Bold.ttf");
|
||||
jreFontMap.put("SourceCodePro italic", "SourceCodePro-It.ttf");
|
||||
jreFontMap.put("SourceCodePro-BoldIt.ttf", new BundledFontInfo("SourceCodePro-BoldIt", 1, 30, 0));
|
||||
jreFontMap.put("SourceCodePro-Regular.ttf", new BundledFontInfo("SourceCodePro-Regular", 2, 10, 0));
|
||||
jreFontMap.put("SourceCodePro-Bold.ttf", new BundledFontInfo("SourceCodePro-Bold", 2, 10, 0));
|
||||
jreFontMap.put("SourceCodePro-It.ttf", new BundledFontInfo("SourceCodePro-It", 1, 30, 0));
|
||||
|
||||
jreFontMap.put("Inconsolata", "Inconsolata.ttf");
|
||||
jreFontMap.put("Inconsolata.ttf", new BundledFontInfo("Inconsolata", 1, 10, 0));
|
||||
|
||||
jreFontMap.put("Roboto light", "Roboto-Light.ttf");
|
||||
jreFontMap.put("Roboto thin", "Roboto-Thin.ttf");
|
||||
jreFontMap.put("Roboto-Light.ttf", new BundledFontInfo("Roboto-Light", 1, 100141, 0));
|
||||
jreFontMap.put("Roboto-Thin.ttf", new BundledFontInfo("Roboto-Thin", 1, 100141, 0));
|
||||
|
||||
jreFamilyMap.put("Roboto-Light", "Roboto Light");
|
||||
jreFamilyMap.put("Roboto-Thin", "Roboto Thin");
|
||||
|
||||
jreFontMap.put("JetBrains Mono Bold", "JetBrainsMono-Bold.ttf");
|
||||
jreFontMap.put("JetBrains Mono Regular", "JetBrainsMono-Regular.ttf");
|
||||
jreFontMap.put("JetBrains Mono Italic", "JetBrainsMono-Italic.ttf");
|
||||
jreFontMap.put("JetBrains Mono Bold Italic", "JetBrainsMono-Bold-Italic.ttf");
|
||||
jreFontMap.put("JetBrainsMono-Bold.ttf", new BundledFontInfo("JetBrainsMono-Bold", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Regular.ttf", new BundledFontInfo("JetBrainsMono-Regular", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Italic.ttf", new BundledFontInfo("JetBrainsMono-Italic", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Bold-Italic.ttf", new BundledFontInfo("JetBrainsMono-BoldItalic", 1, 0, 2));
|
||||
|
||||
jreBundledFontFiles.addAll(jreFontMap.values());
|
||||
jreBundledFontFiles.addAll(jreFontMap.keySet());
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -353,6 +381,9 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
default: throw new RuntimeException("Unexpected address size");
|
||||
}
|
||||
|
||||
versionCheckEnabled =
|
||||
!("true".equals(System.getProperty("java2d.font.noVersionCheck")));
|
||||
|
||||
noType1Font =
|
||||
"true".equals(System.getProperty("sun.java2d.noType1Font"));
|
||||
jreLibDirName =
|
||||
@@ -3887,4 +3918,90 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
public boolean areColorGlyphsSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected BundledFontInfo getBundledFontInfo(String fileName) {
|
||||
return jreFontMap.get(fileName);
|
||||
}
|
||||
|
||||
protected static boolean parseFontVersion(String versionString, int[] version) {
|
||||
int i = 0;
|
||||
boolean foundDigit = false;
|
||||
version[0] = version[1] = version[2] = 0;
|
||||
|
||||
// Skip prefix letters
|
||||
while (i < versionString.length() &&
|
||||
!(foundDigit = Character.isDigit(versionString.charAt(i)))) {
|
||||
i++;
|
||||
}
|
||||
if (!foundDigit) {
|
||||
return false;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
boolean foundDot = false;
|
||||
// Read major version
|
||||
while (i < versionString.length() &&
|
||||
!(foundDot = (versionString.charAt(i) == '.')) &&
|
||||
Character.isDigit(versionString.charAt(i))) {
|
||||
buf.append(versionString.charAt(i));
|
||||
i++;
|
||||
}
|
||||
try {
|
||||
version[0] = Integer.parseInt(buf.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!foundDot) {
|
||||
return true;
|
||||
}
|
||||
buf.setLength(0);
|
||||
i++;
|
||||
foundDigit = false;
|
||||
|
||||
// Read minor version
|
||||
while (i < versionString.length() &&
|
||||
!(foundDot = (versionString.charAt(i) == '.')) &&
|
||||
Character.isDigit(versionString.charAt(i))) {
|
||||
buf.append(versionString.charAt(i));
|
||||
foundDigit = true;
|
||||
i++;
|
||||
}
|
||||
if (!foundDigit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
version[1] = Integer.parseInt(buf.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!foundDot) {
|
||||
return true;
|
||||
}
|
||||
|
||||
buf.setLength(0);
|
||||
i++;
|
||||
foundDigit = false;
|
||||
|
||||
// Read bugfix version
|
||||
while (i < versionString.length() &&
|
||||
!(versionString.charAt(i) == '.') &&
|
||||
Character.isDigit(versionString.charAt(i))) {
|
||||
buf.append(versionString.charAt(i));
|
||||
foundDigit = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!foundDigit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
version[2] = Integer.parseInt(buf.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,15 @@ public class TrueTypeFont extends FileFont {
|
||||
private String localeFullName;
|
||||
|
||||
private Byte supportedCharset;
|
||||
private int fontDataSize;
|
||||
|
||||
/*
|
||||
* Used on Windows to validate the font selected by GDI for (sub-pixel
|
||||
* antialiased) rendering. For 'standalone' fonts it's equal to the font
|
||||
* file size, for collection (TTC, OTC) members it's the number of bytes in
|
||||
* the collection file from the start of this font's offset table till the
|
||||
* end of the file.
|
||||
*/
|
||||
int fontDataSize;
|
||||
|
||||
public TrueTypeFont(String platname, Object nativeNames, int fIndex,
|
||||
boolean javaRasterizer)
|
||||
@@ -1783,11 +1791,6 @@ public class TrueTypeFont extends FileFont {
|
||||
|
||||
private static native void getSupportedCharsetsForFamily(String familyName, Map<String, Byte> supportedCharsets);
|
||||
|
||||
@Override
|
||||
int getFontDataSize() {
|
||||
return fontDataSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "** TrueType Font: Family="+familyName+ " Name="+fullName+
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package sun.java2d.opengl;
|
||||
|
||||
import sun.awt.AWTThreading;
|
||||
import sun.awt.util.ThreadGroupUtils;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
@@ -32,6 +33,7 @@ import sun.java2d.pipe.RenderQueue;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* OGL-specific implementation of RenderQueue. This class provides a
|
||||
@@ -153,7 +155,7 @@ public class OGLRenderQueue extends RenderQueue {
|
||||
}
|
||||
|
||||
private class QueueFlusher implements Runnable {
|
||||
private boolean needsFlush;
|
||||
private volatile boolean needsFlush;
|
||||
private Runnable task;
|
||||
private Error error;
|
||||
private final Thread thread;
|
||||
@@ -167,28 +169,49 @@ public class OGLRenderQueue extends RenderQueue {
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public synchronized void flushNow() {
|
||||
// wake up the flusher
|
||||
needsFlush = true;
|
||||
notify();
|
||||
public void flushNow() {
|
||||
flushNow(null);
|
||||
}
|
||||
|
||||
// wait for flush to complete
|
||||
while (needsFlush) {
|
||||
private void flushNow(Runnable task) {
|
||||
Error err;
|
||||
synchronized (this) {
|
||||
if (task != null) {
|
||||
this.task = task;
|
||||
}
|
||||
// wake up the flusher
|
||||
needsFlush = true;
|
||||
notifyAll();
|
||||
|
||||
// wait for flush to complete
|
||||
try {
|
||||
wait();
|
||||
wait(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
err = error;
|
||||
}
|
||||
if (needsFlush) {
|
||||
// if we still wait for flush then avoid potential deadlock
|
||||
err = AWTThreading.executeWaitToolkit(() -> {
|
||||
synchronized (QueueFlusher.this) {
|
||||
while (needsFlush) {
|
||||
try {
|
||||
QueueFlusher.this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// re-throw any error that may have occurred during the flush
|
||||
if (error != null) {
|
||||
throw error;
|
||||
if (err != null) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void flushAndInvokeNow(Runnable task) {
|
||||
this.task = task;
|
||||
flushNow();
|
||||
public void flushAndInvokeNow(Runnable task) {
|
||||
flushNow(task);
|
||||
}
|
||||
|
||||
public synchronized void run() {
|
||||
@@ -242,7 +265,7 @@ public class OGLRenderQueue extends RenderQueue {
|
||||
task = null;
|
||||
// allow the waiting thread to continue
|
||||
needsFlush = false;
|
||||
notify();
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
import java.text.BreakIterator;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -103,9 +104,11 @@ import sun.font.FontUtilities;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.print.ProxyPrintGraphics;
|
||||
|
||||
import static java.awt.RenderingHints.KEY_FRACTIONALMETRICS;
|
||||
import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
|
||||
import static java.awt.RenderingHints.KEY_TEXT_LCD_CONTRAST;
|
||||
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT;
|
||||
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
|
||||
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
|
||||
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
|
||||
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
|
||||
@@ -566,25 +569,9 @@ public class SwingUtilities2 {
|
||||
? null
|
||||
: c.getClientProperty(KEY_TEXT_ANTIALIASING);
|
||||
if (aaHint != null) {
|
||||
Object oldContrast = null;
|
||||
Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
|
||||
if (aaHint != oldAAValue) {
|
||||
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, aaHint);
|
||||
} else {
|
||||
oldAAValue = null;
|
||||
}
|
||||
|
||||
Object lcdContrastHint = c.getClientProperty(
|
||||
KEY_TEXT_LCD_CONTRAST);
|
||||
if (lcdContrastHint != null) {
|
||||
oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST);
|
||||
if (lcdContrastHint.equals(oldContrast)) {
|
||||
oldContrast = null;
|
||||
} else {
|
||||
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST,
|
||||
lcdContrastHint);
|
||||
}
|
||||
}
|
||||
Object oldAAValue = configureHint(KEY_TEXT_ANTIALIASING, g2, aaHint);
|
||||
Object oldFMValue = configureHint(KEY_FRACTIONALMETRICS, g2, c);
|
||||
Object oldContrast = configureHint(KEY_TEXT_LCD_CONTRAST, g2, c);
|
||||
|
||||
if (needsTextLayout) {
|
||||
TextLayout layout = createTextLayout(c, text, g2.getFont(),
|
||||
@@ -594,12 +581,9 @@ public class SwingUtilities2 {
|
||||
g2.drawString(text, x, y);
|
||||
}
|
||||
|
||||
if (oldAAValue != null) {
|
||||
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
|
||||
}
|
||||
if (oldContrast != null) {
|
||||
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast);
|
||||
}
|
||||
restoreHint(KEY_TEXT_ANTIALIASING, g2, oldAAValue);
|
||||
restoreHint(KEY_FRACTIONALMETRICS, g2, oldFMValue);
|
||||
restoreHint(KEY_TEXT_LCD_CONTRAST, g2, oldContrast);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -905,34 +889,15 @@ public class SwingUtilities2 {
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
if (aaHint != null) {
|
||||
|
||||
Object oldContrast = null;
|
||||
Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
|
||||
if (aaHint != null && aaHint != oldAAValue) {
|
||||
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, aaHint);
|
||||
} else {
|
||||
oldAAValue = null;
|
||||
}
|
||||
|
||||
Object lcdContrastHint = c.getClientProperty(KEY_TEXT_LCD_CONTRAST);
|
||||
if (lcdContrastHint != null) {
|
||||
oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST);
|
||||
if (lcdContrastHint.equals(oldContrast)) {
|
||||
oldContrast = null;
|
||||
} else {
|
||||
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST,
|
||||
lcdContrastHint);
|
||||
}
|
||||
}
|
||||
Object oldAAValue = configureHint(KEY_TEXT_ANTIALIASING, g2, aaHint);
|
||||
Object oldFMValue = configureHint(KEY_FRACTIONALMETRICS, g2, c);
|
||||
Object oldContrast = configureHint(KEY_TEXT_LCD_CONTRAST, g2, c);
|
||||
|
||||
g2.drawString(new String(data, offset, length), x, y);
|
||||
|
||||
if (oldAAValue != null) {
|
||||
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
|
||||
}
|
||||
if (oldContrast != null) {
|
||||
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast);
|
||||
}
|
||||
restoreHint(KEY_TEXT_ANTIALIASING, g2, oldAAValue);
|
||||
restoreHint(KEY_FRACTIONALMETRICS, g2, oldFMValue);
|
||||
restoreHint(KEY_TEXT_LCD_CONTRAST, g2, oldContrast);
|
||||
}
|
||||
else {
|
||||
g2.drawString(new String(data, offset, length), x, y);
|
||||
@@ -1249,7 +1214,6 @@ public class SwingUtilities2 {
|
||||
*/
|
||||
private static FontRenderContext getFRCProperty(JComponent c) {
|
||||
if (c != null) {
|
||||
|
||||
GraphicsConfiguration gc = c.getGraphicsConfiguration();
|
||||
AffineTransform tx = (gc == null) ? null : gc.getDefaultTransform();
|
||||
if (tx == null && !GraphicsEnvironment.isHeadless()) {
|
||||
@@ -1260,16 +1224,22 @@ public class SwingUtilities2 {
|
||||
.getDefaultTransform();
|
||||
}
|
||||
Object aaHint = c.getClientProperty(KEY_TEXT_ANTIALIASING);
|
||||
return getFRCFromCache(tx, aaHint);
|
||||
if (aaHint == null) aaHint = VALUE_TEXT_ANTIALIAS_DEFAULT;
|
||||
|
||||
Object fmHint = c.getClientProperty(KEY_FRACTIONALMETRICS);
|
||||
if (fmHint == null) fmHint = VALUE_FRACTIONALMETRICS_DEFAULT;
|
||||
|
||||
return getFRCFromCache(tx, aaHint, fmHint);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final Object APP_CONTEXT_FRC_CACHE_KEY = new Object();
|
||||
|
||||
private static FontRenderContext getFRCFromCache(AffineTransform tx,
|
||||
Object aaHint) {
|
||||
if (tx == null && aaHint == null) {
|
||||
private static FontRenderContext getFRCFromCache(AffineTransform tx, Object aaHint, Object fmHint) {
|
||||
if ((tx == null || tx.isIdentity())
|
||||
&& (aaHint == VALUE_TEXT_ANTIALIAS_OFF || aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT)
|
||||
&& (fmHint == VALUE_FRACTIONALMETRICS_OFF || fmHint == VALUE_FRACTIONALMETRICS_DEFAULT)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1283,41 +1253,31 @@ public class SwingUtilities2 {
|
||||
}
|
||||
|
||||
Object key = (tx == null)
|
||||
? aaHint
|
||||
: (aaHint == null ? tx : new KeyPair(tx, aaHint));
|
||||
? new KeyArray(aaHint, fmHint)
|
||||
: new KeyArray(tx, aaHint, fmHint);
|
||||
|
||||
FontRenderContext frc = cache.get(key);
|
||||
if (frc == null) {
|
||||
aaHint = (aaHint == null) ? VALUE_TEXT_ANTIALIAS_OFF : aaHint;
|
||||
frc = new FontRenderContext(tx, aaHint,
|
||||
VALUE_FRACTIONALMETRICS_DEFAULT);
|
||||
cache.put(key, frc);
|
||||
}
|
||||
return frc;
|
||||
return cache.computeIfAbsent(key, k -> new FontRenderContext(tx, aaHint, fmHint));
|
||||
}
|
||||
|
||||
private static class KeyPair {
|
||||
private static class KeyArray {
|
||||
private final Object[] array;
|
||||
|
||||
private final Object key1;
|
||||
private final Object key2;
|
||||
|
||||
public KeyPair(Object key1, Object key2) {
|
||||
this.key1 = key1;
|
||||
this.key2 = key2;
|
||||
KeyArray(Object... array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof KeyPair)) {
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof KeyArray)) {
|
||||
return false;
|
||||
}
|
||||
KeyPair that = (KeyPair) obj;
|
||||
return this.key1.equals(that.key1) && this.key2.equals(that.key2);
|
||||
KeyArray that = (KeyArray) object;
|
||||
return Arrays.equals(that.array, array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return key1.hashCode() + 37 * key2.hashCode();
|
||||
return Arrays.hashCode(array);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2349,4 +2309,45 @@ public class SwingUtilities2 {
|
||||
var oldTx = oldGC != null ? oldGC.getDefaultTransform() : null;
|
||||
return !Objects.equals(newTx, oldTx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key the key of the hint to be set
|
||||
* @param g the graphics to configure
|
||||
* @param c the component that provides a hint value
|
||||
* @return a value previously set in the given graphics,
|
||||
* or {@code null} if a hint value is not set
|
||||
*/
|
||||
private static Object configureHint(RenderingHints.Key key, Graphics2D g, JComponent c) {
|
||||
if (c == null) return null; // component is not specified
|
||||
|
||||
return configureHint(key, g, c.getClientProperty(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key the key of the hint to be set
|
||||
* @param g the graphics to configure
|
||||
* @param newValue the new value to set
|
||||
* @return a value previously set in the given graphics,
|
||||
* or {@code null} if a hint value is not set
|
||||
*/
|
||||
private static Object configureHint(RenderingHints.Key key, Graphics2D g, Object newValue) {
|
||||
if (newValue == null) return null; // new value is not provided
|
||||
|
||||
Object oldValue = g.getRenderingHint(key);
|
||||
if (newValue.equals(oldValue)) return null; // value is not changed
|
||||
|
||||
g.setRenderingHint(key, newValue);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key the key of the hint to be set
|
||||
* @param g the graphics to configure
|
||||
* @param oldValue the stored value to set
|
||||
*/
|
||||
private static void restoreHint(RenderingHints.Key key, Graphics2D g, Object oldValue) {
|
||||
if (oldValue == null) return; // nothing to restore
|
||||
|
||||
g.setRenderingHint(key, oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/java.desktop/share/fonts/JetBrainsMono-Bold-Italic.ttf
Executable file → Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-Bold-Italic.ttf
Executable file → Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-Bold.ttf
Executable file → Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-Bold.ttf
Executable file → Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-Italic.ttf
Executable file → Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-Italic.ttf
Executable file → Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-Regular.ttf
Executable file → Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-Regular.ttf
Executable file → Normal file
Binary file not shown.
@@ -36,6 +36,7 @@ import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import sun.awt.*;
|
||||
import sun.awt.event.TouchEvent;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
@@ -46,6 +47,7 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
private static PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XWindow");
|
||||
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XWindow");
|
||||
private static PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XWindow");
|
||||
private static PlatformLogger touchEventLog = PlatformLogger.getLogger("sun.awt.event.TouchEvent");
|
||||
/* If a motion comes in while a multi-click is pending,
|
||||
* allow a smudge factor so that moving the mouse by a small
|
||||
* amount does not wipe out the multi-click state variables.
|
||||
@@ -57,14 +59,12 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
static long lastButton = 0;
|
||||
static WeakReference<XWindow> lastWindowRef = null;
|
||||
static int clickCount = 0;
|
||||
|
||||
// all touch scrolls are measured in pixels
|
||||
private static int touchBeginX = 0, touchBeginY = 0;
|
||||
private static int trackingId = 0;
|
||||
private static long lastTouchUpdateTime = 0;
|
||||
private static boolean isTouchScroll = false;
|
||||
private static final int TOUCH_CLICK_RADIUS = 10;
|
||||
// all touch scrolls are measured in pixels
|
||||
private static final int TOUCH_BEGIN = 2;
|
||||
private static final int TOUCH_UPDATE = 3;
|
||||
private static final int TOUCH_END = 4;
|
||||
|
||||
// used to check if we need to re-create surfaceData.
|
||||
int oldWidth = -1;
|
||||
@@ -800,42 +800,61 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
x = localXY.x;
|
||||
y = localXY.y;
|
||||
}
|
||||
|
||||
int button = XConstants.buttons[0];
|
||||
int modifiers = getModifiers(dev.get_mods().get_effective(), button, 0);
|
||||
// turning off shift modifier
|
||||
modifiers &= ~InputEvent.SHIFT_DOWN_MASK;
|
||||
int modifiers = getModifiers(dev.get_mods().get_effective(), MouseEvent.BUTTON1, 0);
|
||||
int scrollModifiers = modifiers & ~InputEvent.SHIFT_DOWN_MASK;
|
||||
|
||||
long jWhen = XToolkit.nowMillisUTC_offset(dev.get_time());
|
||||
|
||||
switch (dev.get_evtype()) {
|
||||
case XConstants.XI_TouchBegin:
|
||||
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
touchEventLog.finest("Touch Begin at: " + x + ", " + y);
|
||||
}
|
||||
isTouchScroll = false;
|
||||
touchBeginX = x;
|
||||
touchBeginY = y;
|
||||
sendWheelEventFromTouch(dev, jWhen, modifiers, touchBeginX, touchBeginY, TOUCH_BEGIN, 1);
|
||||
lastTouchUpdateTime = jWhen;
|
||||
sendWheelEventFromTouch(dev, jWhen, scrollModifiers, touchBeginX, touchBeginY, TouchEvent.TOUCH_BEGIN, 1);
|
||||
break;
|
||||
case XConstants.XI_TouchUpdate:
|
||||
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
touchEventLog.finest("Touch Update at: " + x + ", " + y);
|
||||
}
|
||||
lastTouchUpdateTime = jWhen;
|
||||
|
||||
if (!isTouchScroll && isInsideTouchClickBoundaries(x, y)) {
|
||||
return;
|
||||
}
|
||||
isTouchScroll = true;
|
||||
|
||||
if (lastY - y != 0) {
|
||||
sendWheelEventFromTouch(dev, jWhen, modifiers, x, y, TOUCH_UPDATE, lastY - y);
|
||||
int deltaY = lastY - y;
|
||||
if (deltaY != 0) {
|
||||
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
touchEventLog.finest("Vertical touch scroll, delta: " + deltaY);
|
||||
}
|
||||
sendWheelEventFromTouch(dev, jWhen, scrollModifiers, x, y, TouchEvent.TOUCH_UPDATE, deltaY);
|
||||
}
|
||||
// horizontal scroll
|
||||
if (lastX - x != 0) {
|
||||
modifiers |= InputEvent.SHIFT_DOWN_MASK;
|
||||
sendWheelEventFromTouch(dev, jWhen, modifiers, x, y, TOUCH_UPDATE, lastX - x);
|
||||
|
||||
int deltaX = lastX - x;
|
||||
if (deltaX != 0) {
|
||||
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
touchEventLog.finest("Horizontal touch scroll, delta: " + deltaX);
|
||||
}
|
||||
int horizontalScrollMods = scrollModifiers | InputEvent.SHIFT_DOWN_MASK;
|
||||
sendWheelEventFromTouch(dev, jWhen, horizontalScrollMods, x, y, TouchEvent.TOUCH_UPDATE, deltaX);
|
||||
}
|
||||
break;
|
||||
case XConstants.XI_TouchEnd:
|
||||
sendWheelEventFromTouch(dev, jWhen, modifiers, x, y, TOUCH_END, 1);
|
||||
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
touchEventLog.finest("Touch End at: " + x + ", " + y);
|
||||
}
|
||||
sendWheelEventFromTouch(dev, jWhen, scrollModifiers, x, y, TouchEvent.TOUCH_END, 1);
|
||||
|
||||
if (!isTouchScroll) {
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_PRESSED, jWhen, modifiers, touchBeginX, touchBeginY, button);
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_RELEASED, jWhen, modifiers, touchBeginX, touchBeginY, button);
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_CLICKED, jWhen, modifiers, touchBeginX, touchBeginY, button);
|
||||
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
touchEventLog.finest("Touch Press at: " + x + ", " + y);
|
||||
}
|
||||
sendButtonPressFromTouch(dev, jWhen, modifiers, touchBeginX, touchBeginY);
|
||||
}
|
||||
|
||||
// release touch processing
|
||||
@@ -848,8 +867,8 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
}
|
||||
|
||||
private boolean isInsideTouchClickBoundaries(int x, int y) {
|
||||
return Math.abs(touchBeginX - x) <= TOUCH_CLICK_RADIUS &&
|
||||
Math.abs(touchBeginY - y) <= TOUCH_CLICK_RADIUS;
|
||||
return Math.abs(touchBeginX - x) <= TouchEvent.CLICK_RADIUS &&
|
||||
Math.abs(touchBeginY - y) <= TouchEvent.CLICK_RADIUS;
|
||||
}
|
||||
|
||||
private static boolean isOwningTouch(int fingerId) {
|
||||
@@ -857,7 +876,24 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
}
|
||||
|
||||
private static boolean isTouchReleased() {
|
||||
return trackingId == 0;
|
||||
if (trackingId == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// recovery from situation when TOUCH_END event didn't occurred
|
||||
long msFromLastUpdate = Math.abs(System.currentTimeMillis() - lastTouchUpdateTime);
|
||||
if (msFromLastUpdate >= TouchEvent.NO_UPDATE_TIMEOUT) {
|
||||
touchEventLog.warning("Release touch processing, milliseconds from last update: " + msFromLastUpdate);
|
||||
}
|
||||
return msFromLastUpdate >= TouchEvent.NO_UPDATE_TIMEOUT;
|
||||
}
|
||||
|
||||
private void sendButtonPressFromTouch(XIDeviceEvent dev, long jWhen, int modifiers, int x, int y) {
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_MOVED, jWhen, modifiers, x, y, MouseEvent.NOBUTTON, 0);
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_DRAGGED, jWhen, modifiers, x, y, MouseEvent.BUTTON1, 0);
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_PRESSED, jWhen, modifiers, x, y, MouseEvent.BUTTON1, 1);
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_RELEASED, jWhen, modifiers, x, y, MouseEvent.BUTTON1, 1);
|
||||
sendMouseEventFromTouch(dev, MouseEvent.MOUSE_CLICKED, jWhen, modifiers, x, y, MouseEvent.BUTTON1, 1);
|
||||
}
|
||||
|
||||
private void sendWheelEventFromTouch(XIDeviceEvent dev, long jWhen, int modifiers, int x, int y, int type, int delta) {
|
||||
@@ -871,15 +907,14 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
1, delta));
|
||||
}
|
||||
|
||||
private void sendMouseEventFromTouch(XIDeviceEvent dev, int type, long jWhen, int modifiers, int x, int y, int button) {
|
||||
private void sendMouseEventFromTouch(XIDeviceEvent dev, int type, long jWhen, int modifiers, int x, int y, int button, int clickCount) {
|
||||
boolean popupTrigger = button == MouseEvent.BUTTON3;
|
||||
postEventToEventQueue(
|
||||
new MouseEvent(getEventSource(), type, jWhen,
|
||||
modifiers,
|
||||
x, y,
|
||||
modifiers, x, y,
|
||||
scaleDown((int) dev.get_root_x()),
|
||||
scaleDown((int) dev.get_root_y()),
|
||||
1,
|
||||
false, button));
|
||||
clickCount, popupTrigger, button));
|
||||
}
|
||||
|
||||
public void handleMotionNotify(XEvent xev) {
|
||||
|
||||
@@ -54,7 +54,7 @@ import sun.awt.X11GraphicsEnvironment;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import sun.security.action.GetBooleanAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
DisplayChangedListener {
|
||||
@@ -66,11 +66,13 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XWindowPeer");
|
||||
|
||||
// workaround for JBR-1680 (see https://youtrack.jetbrains.com/issue/JBR-1680#focus=streamItem-27-3821223.0-0)
|
||||
private static final boolean X11_DISABLE_OVERRIDE_FLAG = AccessController.doPrivileged(
|
||||
new GetBooleanAction("x11.disable.override.flag"));
|
||||
private static final boolean X11_DISABLE_OVERRIDE_XWINDOWPEER = AccessController.doPrivileged(
|
||||
new GetBooleanAction("x11.disable.override.xwindowpeer"));
|
||||
|
||||
//
|
||||
// enable X11_DISABLE_OVERRIDE_FLAG by default (users haven't found side-effects), see
|
||||
// https://youtrack.jetbrains.com/issue/JBR-1680#focus=streamItem-27-3924178.0-0
|
||||
private static final boolean X11_DISABLE_OVERRIDE_FLAG =
|
||||
GetPropertyAction.privilegedGetProperty("x11.disable.override.flag", "true").equalsIgnoreCase("true");
|
||||
private static final boolean X11_DISABLE_OVERRIDE_XWINDOWPEER =
|
||||
GetPropertyAction.privilegedGetProperty("x11.disable.override.xwindowpeer", "false").equalsIgnoreCase("true");
|
||||
|
||||
// should be synchronized on awtLock
|
||||
private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include <java_awt_event_InputEvent.h>
|
||||
#include <java_awt_event_ActionEvent.h>
|
||||
#include <java_awt_event_InputMethodEvent.h>
|
||||
#include <sun_awt_event_TouchEvent.h>
|
||||
#include <sun_awt_windows_WInputMethod.h>
|
||||
#include <java_awt_event_MouseEvent.h>
|
||||
#include <java_awt_event_MouseWheelEvent.h>
|
||||
@@ -226,7 +227,7 @@ AwtComponent::AwtComponent()
|
||||
m_mouseButtonClickAllowed = 0;
|
||||
|
||||
m_isTouchScroll = FALSE;
|
||||
m_touchDownPoint = {0, 0};
|
||||
m_touchBeginPoint = {0, 0};
|
||||
m_lastTouchPoint = {0, 0};
|
||||
|
||||
m_callbacksEnabled = FALSE;
|
||||
@@ -2404,8 +2405,8 @@ void AwtComponent::WmTouch(WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
BOOL AwtComponent::IsInsideTouchClickBoundaries(POINT p)
|
||||
{
|
||||
return abs(p.x - m_touchDownPoint.x) <= TOUCH_MOUSE_COORDS_DELTA &&
|
||||
abs(p.y - m_touchDownPoint.y) <= TOUCH_MOUSE_COORDS_DELTA;
|
||||
return abs(p.x - m_touchBeginPoint.x) <= sun_awt_event_TouchEvent_CLICK_RADIUS &&
|
||||
abs(p.y - m_touchBeginPoint.y) <= sun_awt_event_TouchEvent_CLICK_RADIUS;
|
||||
}
|
||||
|
||||
POINT AwtComponent::TouchCoordsToLocal(LONG x, LONG y)
|
||||
@@ -2418,17 +2419,24 @@ POINT AwtComponent::TouchCoordsToLocal(LONG x, LONG y)
|
||||
void AwtComponent::SendMouseWheelEventFromTouch(POINT p, jint modifiers, jint scrollType, jint pixels)
|
||||
{
|
||||
SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, ::JVM_CurrentTimeMillis(NULL, 0),
|
||||
p.x, p.y, modifiers, 0, 0, scrollType,
|
||||
/*scrollAmount*/ 1, pixels,
|
||||
p.x, p.y, modifiers, /*clickCount*/ 0, /*popupTrigger*/ JNI_FALSE,
|
||||
scrollType, /*scrollAmount*/ 1, pixels,
|
||||
static_cast<double>(pixels), /*msg*/ nullptr);
|
||||
}
|
||||
|
||||
void AwtComponent::SendMouseEventFromTouch(jint id, POINT p, jint modifiers)
|
||||
void AwtComponent::SendMouseEventFromTouch(jint id, POINT p, jint modifiers, jint clickCount, jint button)
|
||||
{
|
||||
SendMouseEvent(id, ::JVM_CurrentTimeMillis(NULL, 0), p.x, p.y,
|
||||
modifiers, /*clickCount*/ 1, JNI_FALSE,
|
||||
java_awt_event_MouseEvent_BUTTON1,
|
||||
/*msg*/ nullptr, /*causedByTouchEvent*/ TRUE);
|
||||
modifiers, clickCount, /*popupTrigger*/ JNI_FALSE,
|
||||
button, /*msg*/ nullptr, /*causedByTouchEvent*/ TRUE);
|
||||
}
|
||||
|
||||
void AwtComponent::SendButtonPressEventFromTouch(POINT p, jint modifiers)
|
||||
{
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_MOVED, p, modifiers, 0, java_awt_event_MouseEvent_NOBUTTON);
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_PRESSED, p, modifiers, 1, java_awt_event_MouseEvent_BUTTON1);
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_RELEASED, p, modifiers, 1, java_awt_event_MouseEvent_BUTTON1);
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_CLICKED, p, modifiers, 1, java_awt_event_MouseEvent_BUTTON1);
|
||||
}
|
||||
|
||||
void AwtComponent::WmTouchHandler(const TOUCHINPUT& touchInput)
|
||||
@@ -2438,43 +2446,39 @@ void AwtComponent::WmTouchHandler(const TOUCHINPUT& touchInput)
|
||||
return;
|
||||
}
|
||||
|
||||
jint modifiers = GetJavaModifiers();
|
||||
// turn off horizontal
|
||||
modifiers &= ~java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
const jint modifiers = GetJavaModifiers();
|
||||
const POINT p = TouchCoordsToLocal(touchInput.x, touchInput.y);
|
||||
|
||||
if (touchInput.dwFlags & TOUCHEVENTF_DOWN) {
|
||||
m_touchDownPoint = p;
|
||||
m_lastTouchPoint = p;
|
||||
m_touchBeginPoint = p;
|
||||
m_isTouchScroll = FALSE;
|
||||
SendMouseWheelEventFromTouch(p, modifiers, TOUCH_BEGIN, 1);
|
||||
SendMouseWheelEventFromTouch(p, modifiers, sun_awt_event_TouchEvent_TOUCH_BEGIN, 1);
|
||||
} else if (touchInput.dwFlags & TOUCHEVENTF_MOVE) {
|
||||
if (!m_isTouchScroll && IsInsideTouchClickBoundaries(p)) {
|
||||
return;
|
||||
}
|
||||
m_isTouchScroll = TRUE;
|
||||
|
||||
const int deltaY = ScaleDownY(static_cast<int>(m_lastTouchPoint.y - p.y));
|
||||
if (abs(deltaY) != 0) {
|
||||
SendMouseWheelEventFromTouch(p, modifiers, TOUCH_UPDATE, deltaY);
|
||||
const jint deltaY = ScaleDownY(static_cast<int>(m_lastTouchPoint.y - p.y));
|
||||
if (deltaY != 0) {
|
||||
const jint scrollModifiers = modifiers & ~java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
SendMouseWheelEventFromTouch(p, scrollModifiers, sun_awt_event_TouchEvent_TOUCH_UPDATE, deltaY);
|
||||
}
|
||||
|
||||
const int deltaX = ScaleDownX(static_cast<int>(m_lastTouchPoint.x - p.x));
|
||||
if (abs(deltaX) != 0) {
|
||||
modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
SendMouseWheelEventFromTouch(p, modifiers, TOUCH_UPDATE, deltaX);
|
||||
const jint deltaX = ScaleDownX(static_cast<int>(m_lastTouchPoint.x - p.x));
|
||||
if (deltaX != 0) {
|
||||
const jint scrollModifiers = modifiers | java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
SendMouseWheelEventFromTouch(p, scrollModifiers, sun_awt_event_TouchEvent_TOUCH_UPDATE, deltaX);
|
||||
}
|
||||
|
||||
m_lastTouchPoint = p;
|
||||
} else if (touchInput.dwFlags & TOUCHEVENTF_UP) {
|
||||
SendMouseWheelEventFromTouch(p, modifiers, TOUCH_END, 1);
|
||||
SendMouseWheelEventFromTouch(p, modifiers, sun_awt_event_TouchEvent_TOUCH_END, 1);
|
||||
|
||||
if (!m_isTouchScroll) {
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_PRESSED, p, modifiers);
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_RELEASED, p, modifiers);
|
||||
SendMouseEventFromTouch(java_awt_event_MouseEvent_MOUSE_CLICKED, p, modifiers);
|
||||
SendButtonPressEventFromTouch(p, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
m_lastTouchPoint = p;
|
||||
}
|
||||
|
||||
/* Double-click variables. */
|
||||
|
||||
@@ -69,14 +69,6 @@ const UINT MAX_ACP_STR_LEN = 7; // ANSI CP identifiers are no longer than this
|
||||
const int ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON;
|
||||
const int X_BUTTONS = MK_XBUTTON1|MK_XBUTTON2;
|
||||
|
||||
// The allowable difference between coordinates of the WM_TOUCH event and the
|
||||
// corresponding WM_LBUTTONDOWN/WM_LBUTTONUP event letting to associate these
|
||||
// events, when their coordinates are slightly different.
|
||||
const int TOUCH_MOUSE_COORDS_DELTA = 10;
|
||||
const int TOUCH_BEGIN = 2;
|
||||
const int TOUCH_UPDATE = 3;
|
||||
const int TOUCH_END = 4;
|
||||
|
||||
// Whether to check for embedded frame and adjust location
|
||||
#define CHECK_EMBEDDED 0
|
||||
#define DONT_CHECK_EMBEDDED 1
|
||||
@@ -541,7 +533,8 @@ public:
|
||||
BOOL IsInsideTouchClickBoundaries(POINT p);
|
||||
POINT TouchCoordsToLocal(LONG x, LONG y);
|
||||
void SendMouseWheelEventFromTouch(POINT p, jint modifiers, jint scrollType, jint pixels);
|
||||
void SendMouseEventFromTouch(jint id, POINT p, jint modifiers);
|
||||
void SendMouseEventFromTouch(jint id, POINT p, jint modifiers, jint clickCount, jint button);
|
||||
void SendButtonPressEventFromTouch(POINT p, jint modifiers);
|
||||
|
||||
// NB: 64-bit: vkey is wParam of the message, but other API's take
|
||||
// vkey parameters of type UINT, so we do the cast before dispatching.
|
||||
@@ -792,7 +785,7 @@ private:
|
||||
UINT m_mouseButtonClickAllowed;
|
||||
|
||||
BOOL m_isTouchScroll;
|
||||
POINT m_touchDownPoint;
|
||||
POINT m_touchBeginPoint;
|
||||
POINT m_lastTouchPoint;
|
||||
|
||||
BOOL m_bSubclassed;
|
||||
|
||||
@@ -171,8 +171,9 @@ JNIEXPORT jboolean JNICALL
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_font_FileFontStrike__1getGlyphImageFromWindows
|
||||
(JNIEnv *env, jobject unused, jstring fontFamily, jint style, jint size,
|
||||
jint glyphCode, jboolean fm, jint rotation, jbyte charset, jint fontDataSize) {
|
||||
(JNIEnv *env, jobject unused,
|
||||
jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm,
|
||||
jint rotation, jbyte charset, jint fontDataSize) {
|
||||
|
||||
GLYPHMETRICS glyphMetrics;
|
||||
LOGFONTW lf;
|
||||
@@ -257,10 +258,10 @@ jint glyphCode, jboolean fm, jint rotation, jbyte charset, jint fontDataSize) {
|
||||
oldFont = SelectObject(hMemoryDC, hFont);
|
||||
|
||||
if (fontDataSize > 0) {
|
||||
// We cannot specify via GDI which font file to use,
|
||||
// so we check that it picks the exact font we need by validating font size.
|
||||
// If it doesn't match, we cannot proceed, as same glyph code can correspond
|
||||
// to a completely different glyph in the selected font.
|
||||
// GDI doesn't allow to select a specific font file for drawing, we can
|
||||
// only check that it picks the file we need by validating font size.
|
||||
// If it doesn't match, we cannot proceed, as the same glyph code can
|
||||
// correspond to a completely different glyph in the selected font.
|
||||
actualFontDataSize = GetFontData(hMemoryDC, 0, 0, NULL, 0);
|
||||
if (actualFontDataSize != fontDataSize) {
|
||||
FREE_AND_RETURN;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
@summary Tests that disposing of an empty Frame or a Frame with a MenuBar
|
||||
while it is being created does not crash the VM.
|
||||
@author dpm area=Threads
|
||||
@run applet/timeout=7200 DisposeStressTest.html
|
||||
@run applet/timeout=600 DisposeStressTest.html
|
||||
-->
|
||||
<head>
|
||||
<title>DisposeStressTest</title>
|
||||
|
||||
@@ -83,6 +83,7 @@ public class DisposeStressTest extends Applet
|
||||
public void start ()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
System.out.println("i = " + i);
|
||||
Frame f = new Frame();
|
||||
f.setBounds(10, 10, 10, 10);
|
||||
f.show();
|
||||
|
||||
@@ -38,12 +38,15 @@ import java.awt.Frame;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.Robot;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class TestDispose {
|
||||
|
||||
public static final int TIMEOUT = 30;
|
||||
|
||||
public static Frame frame = null;
|
||||
public static TextArea textArea = null;
|
||||
public static volatile Process worker = null;
|
||||
@@ -57,33 +60,33 @@ public class TestDispose {
|
||||
ex.printStackTrace();
|
||||
throw new RuntimeException("Unexpected failure");
|
||||
}
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame = new JFrame("Test");
|
||||
|
||||
textArea = new TextArea("editable textArea");
|
||||
textArea.setEditable(true);
|
||||
// textArea.setEditable(false); // this testcase passes if textArea is non-editable
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame = new JFrame("Test");
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(textArea);
|
||||
|
||||
textArea = new TextArea("editable textArea");
|
||||
textArea.setEditable(true);
|
||||
// textArea.setEditable(false); // this testcase passes if textArea is non-editable
|
||||
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(textArea);
|
||||
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame.dispose();
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame.dispose();
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
@@ -94,10 +97,21 @@ public class TestDispose {
|
||||
}
|
||||
});
|
||||
|
||||
System.out.println(System.getProperty("java.home")+"/bin/java TestDispose workprocess");
|
||||
worker = Runtime.getRuntime().exec(System.getProperty("java.home")+"/bin/java TestDispose workprocess");
|
||||
worker.waitFor();
|
||||
return;
|
||||
System.out.println(System.getProperty("java.home") + "/bin/java -cp "
|
||||
+ System.getProperty("java.class.path") + " " + TestDispose.class.getName() + " workprocess");
|
||||
worker = new ProcessBuilder(System.getProperty("java.home")+"/bin/java",
|
||||
"-cp", System.getProperty("java.class.path"), TestDispose.class.getName(), "workprocess")
|
||||
.redirectError(ProcessBuilder.Redirect.INHERIT)
|
||||
.start();
|
||||
if(worker.waitFor(TIMEOUT, TimeUnit.SECONDS)) {
|
||||
if(worker.exitValue() != 0) {
|
||||
throw new RuntimeException("TEST ERROR: subprocess has finished abnormally");
|
||||
}
|
||||
System.out.println("TEST PASSED");
|
||||
return;
|
||||
} else {
|
||||
throw new RuntimeException("TEST FAILED: subprocess has not finished for " + TIMEOUT + " sec");
|
||||
}
|
||||
}
|
||||
|
||||
TestDispose app = new TestDispose();
|
||||
|
||||
@@ -38,12 +38,15 @@ import java.awt.Frame;
|
||||
import java.awt.TextField;
|
||||
import java.awt.Robot;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class TestDispose {
|
||||
|
||||
public static final int TIMEOUT = 30;
|
||||
|
||||
public static Frame frame = null;
|
||||
public static TextField textField = null;
|
||||
public static volatile Process worker = null;
|
||||
@@ -58,31 +61,33 @@ public class TestDispose {
|
||||
throw new RuntimeException("Unexpected failure");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame = new JFrame("Test");
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame = new JFrame("Test");
|
||||
|
||||
textField = new TextField("editable textArea");
|
||||
textField.setEditable(true);
|
||||
// textField.setEditable(false); // this testcase passes if textField is non-editable
|
||||
textField = new TextField("editable textArea");
|
||||
textField.setEditable(true);
|
||||
// textField.setEditable(false); // this testcase passes if textField is non-editable
|
||||
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(textField);
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(textField);
|
||||
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame.dispose();
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame.dispose();
|
||||
}
|
||||
});
|
||||
robot.waitForIdle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -94,10 +99,21 @@ public class TestDispose {
|
||||
}
|
||||
});
|
||||
|
||||
System.out.println(System.getProperty("java.home")+"/bin/java TestDispose workprocess");
|
||||
worker = Runtime.getRuntime().exec(System.getProperty("java.home")+"/bin/java TestDispose workprocess");
|
||||
worker.waitFor();
|
||||
return;
|
||||
System.out.println(System.getProperty("java.home") + "/bin/java -cp "
|
||||
+ System.getProperty("java.class.path") + " " + TestDispose.class.getName() + " workprocess");
|
||||
worker = new ProcessBuilder(System.getProperty("java.home")+"/bin/java",
|
||||
"-cp", System.getProperty("java.class.path"), TestDispose.class.getName(), "workprocess")
|
||||
.redirectError(ProcessBuilder.Redirect.INHERIT)
|
||||
.start();
|
||||
if(worker.waitFor(TIMEOUT, TimeUnit.SECONDS)) {
|
||||
if(worker.exitValue() != 0) {
|
||||
throw new RuntimeException("TEST ERROR: subprocess has finished abnormally");
|
||||
}
|
||||
System.out.println("TEST PASSED");
|
||||
return;
|
||||
} else {
|
||||
throw new RuntimeException("TEST FAILED: subprocess has not finished for " + TIMEOUT + " sec");
|
||||
}
|
||||
}
|
||||
|
||||
TestDispose app = new TestDispose();
|
||||
|
||||
140
test/jdk/jb/java/awt/Toolkit/AWTThreadingTest.java
Normal file
140
test/jdk/jb/java/awt/Toolkit/AWTThreadingTest.java
Normal file
@@ -0,0 +1,140 @@
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.awt.InvokeOnToolkitHelper;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
import sun.lwawt.macosx.LWCToolkit;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary tests that AWTThreading can manage a stream of cross EDT/AppKit invocation requests
|
||||
* @requires (os.family == "mac")
|
||||
* @compile --add-exports=java.desktop/sun.lwawt.macosx=ALL-UNNAMED --add-exports=java.desktop/sun.awt=ALL-UNNAMED AWTThreadingTest.java
|
||||
* @run main/othervm --add-exports=java.desktop/sun.lwawt.macosx=ALL-UNNAMED --add-exports=java.desktop/sun.awt=ALL-UNNAMED AWTThreadingTest
|
||||
* @author Anton Tarasov
|
||||
*/
|
||||
public class AWTThreadingTest {
|
||||
static final ReentrantLock LOCK = new ReentrantLock();
|
||||
static final Condition COND = LOCK.newCondition();
|
||||
static final CountDownLatch LATCH = new CountDownLatch(1);
|
||||
|
||||
static JFrame frame;
|
||||
static Thread thread;
|
||||
|
||||
final static AtomicBoolean passed = new AtomicBoolean(true);
|
||||
final static AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
EventQueue.invokeLater(AWTThreadingTest::runGui);
|
||||
|
||||
LATCH.await(5, TimeUnit.SECONDS);
|
||||
|
||||
frame.dispose();
|
||||
thread.interrupt();
|
||||
|
||||
if (!passed.get()) {
|
||||
throw new RuntimeException("Test FAILED!");
|
||||
}
|
||||
System.out.println("Test PASSED");
|
||||
}
|
||||
|
||||
static void runGui() {
|
||||
frame = new JFrame("frame");
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setSize(200, 200);
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
startThread();
|
||||
}
|
||||
});
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
static void startThread() {
|
||||
thread = new Thread(() -> {
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Execute invokeAndWait() from AppKit to EDT
|
||||
//
|
||||
CThreading.executeOnAppKit(() -> {
|
||||
try {
|
||||
LWCToolkit.invokeAndWait(counter::incrementAndGet, Window.getWindows()[0]);
|
||||
} catch (Exception e) {
|
||||
fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// 2. Execute invokeAndBlock() from EDT to AppKit
|
||||
//
|
||||
EventQueue.invokeLater(() -> {
|
||||
passed.set(false);
|
||||
|
||||
Boolean success = InvokeOnToolkitHelper.invokeAndBlock(() -> {
|
||||
try {
|
||||
return CThreading.executeOnAppKit(() -> Boolean.TRUE);
|
||||
} catch (Throwable e) {
|
||||
fail(e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
System.out.println("Success: " + counter.get() + ": " + success);
|
||||
|
||||
passed.set(Boolean.TRUE.equals(success));
|
||||
|
||||
if (passed.get()) {
|
||||
lock(COND::signal);
|
||||
}
|
||||
else {
|
||||
fail(null);
|
||||
}
|
||||
});
|
||||
|
||||
lock(COND::await);
|
||||
}
|
||||
});
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
static void lock(MyRunnable runnable) {
|
||||
LOCK.lock();
|
||||
try {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
LOCK.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
interface MyRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
static void fail(Throwable e) {
|
||||
if (e != null) e.printStackTrace();
|
||||
passed.set(false);
|
||||
LATCH.countDown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.awt.dnd.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-1414. DnD on linux (XToolkit) does not honor HIDPI scale
|
||||
* @requires (os.family == "linux") & (jdk.version.major >= 11)
|
||||
* @author mikhail.grishch@gmail.com
|
||||
* @run main/othervm -Dsun.java2d.uiScale=2 DnDScalingWithHIDPITest 1
|
||||
* @run main/othervm -Dsun.java2d.uiScale=1 DnDScalingWithHIDPITest 2
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=false DnDScalingWithHIDPITest DISABLE_SCALING
|
||||
* @run main/othervm/fail -Dsun.java2d.uiScale=2.5 -Dsun.java2d.uiScale.enabled=true DnDScalingWithHIDPITest 0.5
|
||||
* @comment remove /fail option when JBR-1365 will be fixed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description
|
||||
* Dnd works incorrect in the case if Source and Target components have different HiDPI scaling.
|
||||
* Scaling is controlled by jvm option (-Dsun.java2d.uiScale) instead of GDK_SCALE env var.
|
||||
*
|
||||
* Test creates frame with transferable panel.
|
||||
* Then it executes another process (DropTargetRunner) which creates frame with Target panel.
|
||||
* Scaling of Target Frame is also controlled by jvm option (-Dsun.java2d.uiScale) which is got from
|
||||
* cmd argument of parent process:
|
||||
* * DISABLE_SCALING - disable scaling (set -Dsun.java2d.uiScale.enabled=false)
|
||||
* * another value (except 0) - scaling factor for Target Frame
|
||||
* Test checks correctness of the dragExit, dragEnter, dragOver and drop actions.
|
||||
* Test runs 4 times with various configurations of source and target scaling.
|
||||
*/
|
||||
|
||||
public class DnDScalingWithHIDPITest {
|
||||
//Timeout of child process must be smaller than timeout of test (default - 120s)
|
||||
private static final int CHILD_PROCESS_TIMEOUT = 60;
|
||||
/**
|
||||
* @param args
|
||||
* arg[0] - scaling factor of DropTargetFrame (must be set!)
|
||||
* * DISABLE_SCALING - disable scaling (set -Dsun.java2d.uiScale.enabled=false)
|
||||
* * another value (except 0) - scaling factor for Target Frame
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
DragSourceFrame sourceFrame = new DragSourceFrame("DRAG");
|
||||
Process process = null;
|
||||
boolean processExit = false;
|
||||
try {
|
||||
var r = new Robot();
|
||||
SwingUtilities.invokeAndWait(sourceFrame::initUI);
|
||||
r.waitForIdle();
|
||||
|
||||
String sourceScaleStr = System.getProperty("sun.java2d.uiScale");
|
||||
float sourceScale = 1;
|
||||
if ("false".equals(System.getProperty("sun.java2d.uiScale.enabled"))) {
|
||||
System.out.println("Scaling disabled on DRAG Frame (-Dsun.java2d.uiScale.enabled=false)");
|
||||
} else if(sourceScaleStr == null) {
|
||||
throw new RuntimeException("Error: Property sun.java2d.uiScale did not set");
|
||||
} else {
|
||||
sourceScale = Float.parseFloat(sourceScaleStr);
|
||||
}
|
||||
|
||||
String vmScalingOption;
|
||||
float targetScale = 1;
|
||||
if (args.length == 0) {
|
||||
throw new RuntimeException("Error: Program argument did not set (Scaling value for DROP Frame can not be specified).");
|
||||
} else if ("DISABLE_SCALING".equals(args[0])) {
|
||||
System.out.println("Scaling disabled on DROP Frame (-Dsun.java2d.uiScale.enabled=false)");
|
||||
vmScalingOption = "-Dsun.java2d.uiScale.enabled=false";
|
||||
} else {
|
||||
vmScalingOption = "-Dsun.java2d.uiScale=" + args[0];
|
||||
String targetScaleStr = args[0];
|
||||
targetScale = "0".equals(targetScaleStr) ? 1 : Float.parseFloat(targetScaleStr);
|
||||
}
|
||||
|
||||
float scalingFactor = sourceScale / targetScale;
|
||||
|
||||
var processBuilder = new ProcessBuilder(
|
||||
System.getProperty("java.home") + "/bin/java",
|
||||
vmScalingOption,
|
||||
"-cp",
|
||||
System.getProperty("java.class.path", "."),
|
||||
"DropTargetRunner",
|
||||
String.valueOf((int) (sourceFrame.getNextLocationX() * scalingFactor)),
|
||||
String.valueOf((int) (sourceFrame.getNextLocationY() * scalingFactor)),
|
||||
String.valueOf((int) (sourceFrame.getDragSourcePointX() * scalingFactor)),
|
||||
String.valueOf((int) (sourceFrame.getDragSourcePointY() * scalingFactor))
|
||||
);
|
||||
|
||||
System.out.println("Starting DropTargetRunner...");
|
||||
processBuilder.command().forEach(s -> System.out.print(s + " "));
|
||||
System.out.println("\n");
|
||||
|
||||
process = processBuilder.start();
|
||||
processExit = process.waitFor(CHILD_PROCESS_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
var inContent = new StringBuilder();
|
||||
var errContent = new StringBuilder();
|
||||
getStreamContent(process.getInputStream(), inContent);
|
||||
getStreamContent(process.getErrorStream(), errContent);
|
||||
|
||||
System.out.println(inContent.toString());
|
||||
|
||||
if(!processExit) {
|
||||
process.destroy();
|
||||
processExit = true;
|
||||
throw new RuntimeException("Error: Timeout. The sub-process hangs.");
|
||||
}
|
||||
|
||||
String errorContentStr = errContent.toString();
|
||||
if (!errorContentStr.isEmpty()) {
|
||||
throw new RuntimeException(errorContentStr);
|
||||
}
|
||||
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(sourceFrame::dispose);
|
||||
Thread.sleep(1000);
|
||||
if(process != null && !processExit) {
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void getStreamContent(InputStream in, StringBuilder content) throws IOException {
|
||||
String tempString;
|
||||
int count = in.available();
|
||||
while (count > 0) {
|
||||
byte[] b = new byte[count];
|
||||
in.read(b);
|
||||
tempString = new String(b);
|
||||
content.append(tempString).append("\n");
|
||||
count = in.available();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DragSourceFrame extends JFrame implements DragGestureListener {
|
||||
private JPanel sourcePanel;
|
||||
|
||||
DragSourceFrame(String frameName) {
|
||||
super(frameName);
|
||||
this.setUndecorated(true);
|
||||
}
|
||||
|
||||
void initUI() {
|
||||
this.setLocation(0, 0);
|
||||
JPanel contentPane = new JPanel(null);
|
||||
contentPane.setPreferredSize(new Dimension(100, 100));
|
||||
|
||||
sourcePanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setColor(this.getBackground());
|
||||
g2.fillRect(0, 0, 100, 100);
|
||||
}
|
||||
};
|
||||
sourcePanel.setBounds(0, 0, 100, 100);
|
||||
sourcePanel.setEnabled(true);
|
||||
sourcePanel.setBackground(Color.white);
|
||||
|
||||
var ds = new DragSource();
|
||||
ds.createDefaultDragGestureRecognizer(sourcePanel,
|
||||
DnDConstants.ACTION_COPY, this);
|
||||
|
||||
contentPane.add(sourcePanel);
|
||||
this.setContentPane(contentPane);
|
||||
|
||||
this.pack();
|
||||
this.setVisible(true);
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
// returns the X coordinate on which DropTargetFrame will be opened
|
||||
int getNextLocationX() {
|
||||
return getX() + getWidth();
|
||||
}
|
||||
|
||||
// returns the X coordinate on which DropTargetFrame will be opened
|
||||
int getNextLocationY() {
|
||||
return getY();
|
||||
}
|
||||
|
||||
//returns the X coordinate to drag Source panel
|
||||
int getDragSourcePointX() {
|
||||
return (int) sourcePanel.getLocationOnScreen().getX() + (sourcePanel.getWidth() / 2);
|
||||
}
|
||||
|
||||
//returns the Y coordinate to drag Source panel
|
||||
int getDragSourcePointY() {
|
||||
return (int) sourcePanel.getLocationOnScreen().getY() + (sourcePanel.getHeight() / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragGestureRecognized(DragGestureEvent event) {
|
||||
var cursor = Cursor.getDefaultCursor();
|
||||
if (event.getDragAction() == DnDConstants.ACTION_COPY) {
|
||||
cursor = DragSource.DefaultCopyDrop;
|
||||
}
|
||||
event.startDrag(cursor, new TransferableElement());
|
||||
}
|
||||
}
|
||||
|
||||
class TransferableElement implements Transferable {
|
||||
private static final DataFlavor[] supportedFlavors = {DataFlavor.stringFlavor};
|
||||
|
||||
public TransferableElement() {
|
||||
}
|
||||
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return supportedFlavors;
|
||||
}
|
||||
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return flavor.equals(DataFlavor.stringFlavor);
|
||||
}
|
||||
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
|
||||
if (flavor.equals(DataFlavor.stringFlavor)) {
|
||||
return "Transferable text";
|
||||
} else {
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DropTargetRunner {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* arg[0] - the X coordinate of DropTargetFrame
|
||||
* arg[1] - the Y coordinate of DropTargetFrame
|
||||
* arg[2] - the X coordinate of source panel which will be dragged
|
||||
* arg[2] - the Y coordinate of source panel which will be dragged
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
Robot r = new Robot();
|
||||
DropTargetFrame targetFrame = new DropTargetFrame("DROP", r);
|
||||
try {
|
||||
int dragSourceX = Integer.parseInt(args[2]);
|
||||
int dragSourceY = Integer.parseInt(args[3]);
|
||||
var targetFrameLocation = new Point(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
|
||||
SwingUtilities.invokeAndWait(() -> targetFrame.initUI(targetFrameLocation));
|
||||
r.waitForIdle();
|
||||
targetFrame.doTest(dragSourceX, dragSourceY);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(targetFrame::dispose);
|
||||
r.waitForIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DropTargetFrame extends JFrame {
|
||||
private Robot robot;
|
||||
private JPanel dtPanel;
|
||||
private boolean dropWasSuccessful = false;
|
||||
private boolean dragEnterWasSuccessful = false;
|
||||
private boolean dragOverWasSuccessful = false;
|
||||
private boolean dragExitWasSuccessful = false;
|
||||
|
||||
DropTargetFrame(String frameName, Robot r) {
|
||||
super(frameName);
|
||||
robot = r;
|
||||
}
|
||||
|
||||
void initUI(Point frameLocation) {
|
||||
this.setLocation(frameLocation);
|
||||
JPanel contentPane = new JPanel(null);
|
||||
contentPane.setPreferredSize(new Dimension(400, 400));
|
||||
|
||||
dtPanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setColor(this.getBackground());
|
||||
g2.fillRect(0, 0, 200, 200);
|
||||
}
|
||||
};
|
||||
|
||||
dtPanel.setBounds(100, 100, 200, 200);
|
||||
dtPanel.setEnabled(true);
|
||||
dtPanel.setBackground(Color.white);
|
||||
dtPanel.setDropTarget(new DropTarget(dtPanel, DnDConstants.ACTION_COPY_OR_MOVE, new DropTargetAdapter() {
|
||||
public void dragOver(DropTargetDragEvent dtde) {
|
||||
dragOverWasSuccessful = true;
|
||||
}
|
||||
public void dragExit(DropTargetEvent dte) {
|
||||
dragExitWasSuccessful = true;
|
||||
}
|
||||
public void dragEnter(DropTargetDragEvent dtde) {
|
||||
dragEnterWasSuccessful = true;
|
||||
}
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent dtde) {
|
||||
dropWasSuccessful = true;
|
||||
}
|
||||
|
||||
}, true));
|
||||
|
||||
contentPane.add(dtPanel);
|
||||
this.setContentPane(contentPane);
|
||||
this.pack();
|
||||
this.setVisible(true);
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
void doTest(int dragSourceX, int dragSourceY) {
|
||||
int dtPanelX = (int) dtPanel.getLocationOnScreen().getX();
|
||||
int dtPanelY = (int) dtPanel.getLocationOnScreen().getY();
|
||||
|
||||
System.out.print("Check the inner border in the top left corner...\t");
|
||||
dragAndDrop(dragSourceX, dragSourceY, dtPanelX, dtPanelY);
|
||||
checkDragEnter();
|
||||
checkDragOver();
|
||||
checkNotDragExit();
|
||||
checkDropInsidePanel();
|
||||
System.out.println("OK");
|
||||
|
||||
System.out.print("Check the outer border in the top left corner...\t");
|
||||
drag(dragSourceX, dragSourceY, dtPanelX, dtPanelY);
|
||||
mouseMove(dtPanelX, dtPanelY,dtPanelX - 1, dtPanelY - 1);
|
||||
checkDragExit();
|
||||
drop();
|
||||
checkDropOutsidePanel();
|
||||
System.out.println("OK");
|
||||
|
||||
System.out.print("Check the inner border in the bottom right corner...\t");
|
||||
dragAndDrop(dragSourceX, dragSourceY, dtPanelX + dtPanel.getWidth() - 1, dtPanelY + dtPanel.getHeight() - 1);
|
||||
checkDragEnter();
|
||||
checkDragOver();
|
||||
checkNotDragExit();
|
||||
checkDropInsidePanel();
|
||||
System.out.println("OK");
|
||||
|
||||
System.out.print("Check the outer border in the bottom right corner...\t");
|
||||
drag(dragSourceX, dragSourceY, dtPanelX + dtPanel.getWidth() - 1, dtPanelY + dtPanel.getHeight() - 1);
|
||||
mouseMove(dtPanelX + dtPanel.getWidth() - 1, dtPanelY + dtPanel.getHeight() - 1,
|
||||
dtPanelX + dtPanel.getWidth(), dtPanelY + dtPanel.getHeight());
|
||||
checkDragExit();
|
||||
drop();
|
||||
checkDropOutsidePanel();
|
||||
System.out.println("OK");
|
||||
}
|
||||
|
||||
private void drag(int startX, int startY, int finishX, int finishY) {
|
||||
robot.mouseMove(startX, startY);
|
||||
robot.delay(50);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
Point p = MouseInfo.getPointerInfo().getLocation();
|
||||
mouseMove(p.x, p.y, finishX, finishY);
|
||||
robot.delay(500);
|
||||
}
|
||||
|
||||
private void drop() {
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.delay(500);
|
||||
}
|
||||
|
||||
private void dragAndDrop(int startX, int startY, int finishX, int finishY) {
|
||||
drag(startX, startY, finishX, finishY);
|
||||
drop();
|
||||
}
|
||||
|
||||
private void checkDropInsidePanel() {
|
||||
if (!dropWasSuccessful) {
|
||||
System.out.println("FAILED");
|
||||
throw new RuntimeException("DnD failed: Drop was outside Target panel, but inside is expected");
|
||||
}
|
||||
dropWasSuccessful = false;
|
||||
}
|
||||
|
||||
private void checkDropOutsidePanel() {
|
||||
if (dropWasSuccessful) {
|
||||
System.out.println("FAILED");
|
||||
throw new RuntimeException("DnD failed: Drop was inside Target panel, but outside is expected");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDragExit() {
|
||||
if (!dragExitWasSuccessful) {
|
||||
System.out.println("FAILED");
|
||||
throw new RuntimeException("DnD failed: Drag exit was expected, but did not happened");
|
||||
}
|
||||
dragExitWasSuccessful = false;
|
||||
}
|
||||
|
||||
private void checkNotDragExit() {
|
||||
if (dragExitWasSuccessful) {
|
||||
System.out.println("FAILED");
|
||||
throw new RuntimeException("DnD failed: Unexpected Drag exit");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkDragEnter() {
|
||||
if (!dragEnterWasSuccessful) {
|
||||
System.out.println("FAILED");
|
||||
throw new RuntimeException("DnD failed: Drag enter was expected, but did not happened");
|
||||
}
|
||||
dragEnterWasSuccessful = false;
|
||||
}
|
||||
|
||||
private void checkDragOver() {
|
||||
if (!dragOverWasSuccessful) {
|
||||
System.out.println("FAILED");
|
||||
throw new RuntimeException("DnD failed: Drag over was expected, but did not happened");
|
||||
}
|
||||
dragOverWasSuccessful = false;
|
||||
}
|
||||
|
||||
private void mouseMove(int startX, int startY, int finishX, int finishY) {
|
||||
mouseMove(new Point(startX, startY), new Point(finishX, finishY));
|
||||
}
|
||||
|
||||
private void mouseMove(Point start, Point end) {
|
||||
robot.mouseMove(start.x, start.y);
|
||||
for (Point p = new Point(start); !p.equals(end);
|
||||
p.translate(Integer.compare(end.x - p.x, 0),
|
||||
Integer.compare(end.y - p.y, 0))) {
|
||||
robot.mouseMove(p.x, p.y);
|
||||
robot.delay(10);
|
||||
}
|
||||
robot.mouseMove(end.x, end.y);
|
||||
robot.delay(100);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinuxTouchRobot extends TouchRobot {
|
||||
private LinuxTouchScreenDevice device;
|
||||
|
||||
public LinuxTouchRobot() throws AWTException, IOException {
|
||||
super();
|
||||
device = new LinuxTouchScreenDevice();
|
||||
}
|
||||
|
||||
public LinuxTouchRobot(GraphicsDevice screen) throws AWTException, IOException {
|
||||
super(screen);
|
||||
device = new LinuxTouchScreenDevice();
|
||||
}
|
||||
|
||||
public void touchClick(int fingerId, int x, int y) throws IOException {
|
||||
device.click(fingerId, x, y);
|
||||
}
|
||||
|
||||
public void touchMove(int fingerId, int fromX, int fromY, int toX, int toY) throws IOException {
|
||||
device.move(fingerId, fromX, fromY, toX, toY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinuxTouchScreenDevice implements AutoCloseable {
|
||||
// TODO add product id
|
||||
private int width;
|
||||
private int height;
|
||||
private int fileDescriptor;
|
||||
|
||||
static {
|
||||
System.loadLibrary("touchscreen_device");
|
||||
}
|
||||
|
||||
public LinuxTouchScreenDevice() throws IOException {
|
||||
this(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
|
||||
}
|
||||
|
||||
public LinuxTouchScreenDevice(int width, int height) throws IOException {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
fileDescriptor = create(getWidth(), getHeight());
|
||||
checkCompletion(fileDescriptor,
|
||||
"Failed to create virtual touchscreen device");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
checkCompletion(destroy(fileDescriptor),
|
||||
"Failed to close touchscreen device");
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void click(int trackingId, int x, int y) throws IOException {
|
||||
checkCompletion(clickImpl(fileDescriptor, trackingId, x, y),
|
||||
"Failed to click on touchscreen device");
|
||||
|
||||
}
|
||||
|
||||
public void move(int trackingId, int fromX, int fromY, int toX, int toY) throws IOException {
|
||||
checkCompletion(moveImpl(fileDescriptor, trackingId, fromX, fromY, toX, toY),
|
||||
"Failed to move on virtual touchscreen device");
|
||||
}
|
||||
|
||||
private void checkCompletion(int code, String errorMessage) throws IOException {
|
||||
if (code < 0) {
|
||||
throw new IOException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private native int create(int width, int height);
|
||||
|
||||
private native int destroy(int fd);
|
||||
|
||||
private native int clickImpl(int fd, int trackingId, int x, int y);
|
||||
|
||||
private native int moveImpl(int fd, int trackingId, int fromX, int fromY, int toX, int toY);
|
||||
}
|
||||
|
||||
|
||||
33
test/jdk/jb/java/awt/event/TouchScreenEvent/TouchRobot.java
Normal file
33
test/jdk/jb/java/awt/event/TouchScreenEvent/TouchRobot.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.Robot;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class TouchRobot extends Robot {
|
||||
public TouchRobot() throws AWTException {
|
||||
}
|
||||
|
||||
public TouchRobot(GraphicsDevice screen) throws AWTException {
|
||||
super(screen);
|
||||
}
|
||||
|
||||
public abstract void touchClick(int fingerId, int x, int y) throws IOException;
|
||||
|
||||
public abstract void touchMove(int fingerId, int fromX, int fromY, int toX, int toY) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-2041: Touchscreen devices support
|
||||
* @requires (jdk.version.major >= 11) & (os.family == "windows")
|
||||
* @build WindowsTouchRobot TouchScreenEventsTest
|
||||
* @run main/othervm/native TouchScreenEventsTest
|
||||
*/
|
||||
|
||||
public class TouchScreenEventsTest {
|
||||
|
||||
static final int TIMEOUT = 2;
|
||||
static final int PAUSE = 1000;
|
||||
|
||||
// TODO make this constants accessible within jdk
|
||||
static final int TOUCH_BEGIN = 2;
|
||||
static final int TOUCH_UPDATE = 3;
|
||||
static final int TOUCH_END = 4;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if(runTest(new TouchClickSuite())
|
||||
& runTest(new TouchMoveSuite())
|
||||
& runTest(new TouchTinyMoveSuite())
|
||||
& runTest(new TouchAxesScrollSuite(TouchAxesScrollSuite.AXIS.X))
|
||||
& runTest(new TouchAxesScrollSuite(TouchAxesScrollSuite.AXIS.Y))) {
|
||||
System.out.println("TEST PASSED");
|
||||
} else {
|
||||
throw new RuntimeException("TEST FAILED");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean runTest(TouchTestSuite suite) throws Exception {
|
||||
GUI gui = new GUI();
|
||||
try {
|
||||
TouchRobot robot = getTouchRobot();
|
||||
SwingUtilities.invokeAndWait(gui::createAndShow);
|
||||
suite.addListener(gui.frame);
|
||||
robot.waitForIdle();
|
||||
Thread.sleep(PAUSE);
|
||||
suite.perform(gui, robot);
|
||||
robot.waitForIdle();
|
||||
return suite.passed();
|
||||
} finally {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (gui.frame != null) {
|
||||
gui.frame.dispose();
|
||||
}
|
||||
});
|
||||
Thread.sleep(PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
private static TouchRobot getTouchRobot() throws IOException, AWTException {
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
if (osName.contains("linux")) {
|
||||
return new LinuxTouchRobot();
|
||||
} else if (osName.contains("windows")) {
|
||||
return new WindowsTouchRobot();
|
||||
}
|
||||
throw new RuntimeException("Touch robot for this platform isn't implemented");
|
||||
}
|
||||
}
|
||||
|
||||
class GUI {
|
||||
JFrame frame;
|
||||
Rectangle frameBounds;
|
||||
|
||||
void createAndShow() {
|
||||
frame = new JFrame();
|
||||
frame.setSize(640, 480);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
frameBounds = frame.getBounds();
|
||||
}
|
||||
}
|
||||
|
||||
interface TouchTestSuite {
|
||||
|
||||
void addListener(JFrame frame);
|
||||
|
||||
void perform(GUI gui, TouchRobot robot) throws IOException;
|
||||
|
||||
boolean passed() throws InterruptedException;
|
||||
|
||||
}
|
||||
|
||||
class TouchClickSuite implements MouseListener, TouchTestSuite {
|
||||
|
||||
private volatile boolean pressed;
|
||||
private volatile boolean released;
|
||||
private volatile boolean clicked;
|
||||
private final CountDownLatch latch = new CountDownLatch(3);
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (!clicked) {
|
||||
clicked = true;
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
pressed = true;
|
||||
if (!pressed) {
|
||||
pressed = true;
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (!released) {
|
||||
released = true;
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(GUI gui, TouchRobot robot) throws IOException {
|
||||
int x = gui.frameBounds.x + gui.frameBounds.width / 2;
|
||||
int y = gui.frameBounds.y + gui.frameBounds.height / 2;
|
||||
robot.touchClick(42, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passed() throws InterruptedException {
|
||||
latch.await(TouchScreenEventsTest.TIMEOUT, TimeUnit.SECONDS);
|
||||
if (!pressed || !released || !clicked) {
|
||||
String error = (pressed ? "" : "pressed: " + pressed) +
|
||||
(released ? "" : ", released: " + released) +
|
||||
(clicked ? "" : ", clicked: " + clicked);
|
||||
System.out.println("Touch click failed: " + error);
|
||||
return false;
|
||||
}
|
||||
System.out.println("Touch click passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(JFrame frame) {
|
||||
frame.addMouseListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TouchMoveSuite implements MouseWheelListener, TouchTestSuite {
|
||||
|
||||
private volatile boolean begin;
|
||||
private volatile boolean update;
|
||||
private volatile boolean end;
|
||||
private final CountDownLatch latch = new CountDownLatch(3);
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (e.getScrollType() == TouchScreenEventsTest.TOUCH_BEGIN) {
|
||||
if (!begin) {
|
||||
begin = true;
|
||||
latch.countDown();
|
||||
}
|
||||
} else if (e.getScrollType() == TouchScreenEventsTest.TOUCH_UPDATE) {
|
||||
if (!update) {
|
||||
update = true;
|
||||
latch.countDown();
|
||||
}
|
||||
} else if (e.getScrollType() == TouchScreenEventsTest.TOUCH_END) {
|
||||
if (!end) {
|
||||
end = true;
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(GUI gui, TouchRobot robot) throws IOException {
|
||||
int x1 = gui.frameBounds.x + gui.frameBounds.width / 4;
|
||||
int y1 = gui.frameBounds.y + gui.frameBounds.height / 4;
|
||||
int x2 = gui.frameBounds.x + gui.frameBounds.width / 2;
|
||||
int y2 = gui.frameBounds.y + gui.frameBounds.height / 2;
|
||||
robot.touchMove(42, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passed() throws InterruptedException {
|
||||
latch.await(TouchScreenEventsTest.TIMEOUT, TimeUnit.SECONDS);
|
||||
if (!begin || !update || !end) {
|
||||
String error = (begin ? "" : "begin: " + begin) +
|
||||
(update ? "" : ", update: " + update) +
|
||||
(end ? "" : ", end: " + end);
|
||||
System.out.println("Touch move failed: " + error);
|
||||
return false;
|
||||
}
|
||||
System.out.println("Touch move passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(JFrame frame) {
|
||||
frame.addMouseWheelListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TouchTinyMoveSuite implements MouseWheelListener, MouseListener, TouchTestSuite {
|
||||
|
||||
private volatile boolean scroll;
|
||||
private volatile boolean click;
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (e.getScrollType() == TouchScreenEventsTest.TOUCH_UPDATE) {
|
||||
scroll = true;
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(GUI gui, TouchRobot robot) throws IOException {
|
||||
int x1 = gui.frameBounds.x + gui.frameBounds.width / 4;
|
||||
int y1 = gui.frameBounds.y + gui.frameBounds.height / 4;
|
||||
// move inside tiny area
|
||||
int x2 = x1 + 1;
|
||||
int y2 = y1 + 1;
|
||||
robot.touchMove(42, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passed() throws InterruptedException {
|
||||
latch.await(TouchScreenEventsTest.TIMEOUT, TimeUnit.SECONDS);
|
||||
if (scroll || !click) {
|
||||
String error = (scroll ? "scroll " + scroll : "") +
|
||||
(click ? "" : ", click: " + click);
|
||||
System.out.println("Tiny touch move failed: " + error);
|
||||
return false;
|
||||
}
|
||||
System.out.println("Tiny touch move passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(JFrame frame) {
|
||||
frame.addMouseWheelListener(this);
|
||||
frame.addMouseListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
click = true;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
}
|
||||
|
||||
class TouchAxesScrollSuite implements MouseWheelListener, TouchTestSuite {
|
||||
enum AXIS {X, Y}
|
||||
|
||||
private final AXIS axis;
|
||||
private volatile boolean vertical;
|
||||
private volatile boolean horizontal;
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
TouchAxesScrollSuite(AXIS axis) {
|
||||
this.axis = axis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (e.getScrollType() == TouchScreenEventsTest.TOUCH_UPDATE) {
|
||||
if (e.isShiftDown()) {
|
||||
horizontal = true;
|
||||
} else {
|
||||
vertical = true;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(GUI gui, TouchRobot robot) throws IOException {
|
||||
int x1 = gui.frameBounds.x + gui.frameBounds.width / 4;
|
||||
int y1 = gui.frameBounds.y + gui.frameBounds.height / 4;
|
||||
switch (axis) {
|
||||
case X:
|
||||
int x2 = gui.frameBounds.x + gui.frameBounds.width / 2;
|
||||
robot.touchMove(42, x1, y1, x2, y1);
|
||||
break;
|
||||
case Y:
|
||||
int y2 = gui.frameBounds.y + gui.frameBounds.height / 2;
|
||||
robot.touchMove(42, x1, y1, x1, y2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passed() throws InterruptedException {
|
||||
latch.await(TouchScreenEventsTest.TIMEOUT, TimeUnit.SECONDS);
|
||||
String info = "horizontal: " + horizontal + ", vertical: " + vertical;
|
||||
switch (axis) {
|
||||
case X:
|
||||
if (!horizontal || vertical) {
|
||||
System.out.println("Touch axes failed: " + info);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Y:
|
||||
if (horizontal || !vertical) {
|
||||
System.out.println("Touch axes failed: " + info);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
System.out.println("Touch axes passed: " + info);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(JFrame frame) {
|
||||
frame.addMouseWheelListener(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Copyright 2000-2020 JetBrains s.r.o.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# @test
|
||||
# @summary Regression test for JBR-2041: Touchscreen devices support
|
||||
# @requires (jdk.version.major >= 11) & (os.family == "linux")
|
||||
# @build TouchRobot LinuxTouchRobot LinuxTouchScreenDevice TouchScreenEventsTest
|
||||
# @run shell TouchScreenEventsTestLinux.sh
|
||||
|
||||
# password for sudo
|
||||
PASSWORD=${BUPWD}
|
||||
|
||||
echo "Allow current user write to /dev/uinput:"
|
||||
echo "> sudo chown `whoami` /dev/uinput"
|
||||
echo ${PASSWORD} | sudo -S chown `whoami` /dev/uinput
|
||||
echo "result=$?"
|
||||
|
||||
echo "Launching TouchScreenEventsTest.java:"
|
||||
echo "> $TESTJAVA/bin/java $TESTVMOPTS -cp $TESTCLASSES TouchScreenEventsTest"
|
||||
$TESTJAVA/bin/java $TESTVMOPTS -cp $TESTCLASSES TouchScreenEventsTest
|
||||
result=$?
|
||||
echo "result=$result"
|
||||
|
||||
echo "Restore permissions for /dev/uinput:"
|
||||
echo "> sudo chown root /dev/uinput"
|
||||
echo ${PASSWORD} | sudo -S chown root /dev/uinput
|
||||
echo "result=$?"
|
||||
|
||||
exit $result
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.io.IOException;
|
||||
|
||||
public class WindowsTouchRobot extends TouchRobot {
|
||||
static {
|
||||
System.loadLibrary("windows_touch_robot");
|
||||
}
|
||||
|
||||
public WindowsTouchRobot() throws AWTException, IOException {
|
||||
super();
|
||||
}
|
||||
|
||||
public WindowsTouchRobot(GraphicsDevice screen) throws AWTException, IOException {
|
||||
super(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchClick(int fingerId, int x, int y) throws IOException {
|
||||
// TODO unused finger id cause windows use different finger id model
|
||||
clickImpl(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchMove(int fingerId, int fromX, int fromY, int toX, int toY) throws IOException {
|
||||
// TODO unused finger id cause windows use different finger id model
|
||||
moveImpl(fromX, fromY, toX, toY);
|
||||
}
|
||||
|
||||
private native void clickImpl(int x, int y);
|
||||
|
||||
private native void moveImpl(int fromX, int fromY, int toX, int toY);
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uinput.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// TODO sort includes
|
||||
// TODO add casts
|
||||
|
||||
typedef struct {
|
||||
__u16 type;
|
||||
__u16 code;
|
||||
__s32 value;
|
||||
} TEventData;
|
||||
|
||||
static int set_bit(int fd, unsigned long int request, unsigned long int bit) {
|
||||
return ioctl(fd, request, bit);
|
||||
}
|
||||
|
||||
static int touch_begin(int fd, int tracking_id, int x, int y) {
|
||||
struct input_event ev;
|
||||
int i = 0;
|
||||
const int cnt = 7;
|
||||
TEventData eventData[7] = {{EV_ABS, ABS_MT_TRACKING_ID, tracking_id},
|
||||
{EV_ABS, ABS_MT_POSITION_X, x},
|
||||
{EV_ABS, ABS_MT_POSITION_Y, y},
|
||||
{EV_KEY, BTN_TOUCH, 1},
|
||||
{EV_ABS, ABS_X, x},
|
||||
{EV_ABS, ABS_Y, y},
|
||||
{EV_SYN, 0, 0}};
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
memset(&ev, 0, sizeof(struct input_event));
|
||||
ev.type = eventData[i].type;
|
||||
ev.code = eventData[i].code;
|
||||
ev.value = eventData[i].value;
|
||||
|
||||
if (write(fd, &ev, sizeof(struct input_event)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int touch_update(int fd, int x, int y) {
|
||||
struct input_event ev;
|
||||
int i = 0;
|
||||
const int cnt = 5;
|
||||
TEventData eventData[5] = {{EV_ABS, ABS_MT_POSITION_X, x},
|
||||
{EV_ABS, ABS_MT_POSITION_Y, y},
|
||||
{EV_ABS, ABS_X, x},
|
||||
{EV_ABS, ABS_Y, y},
|
||||
{EV_SYN, 0, 0}};
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
memset(&ev, 0, sizeof(struct input_event));
|
||||
ev.type = eventData[i].type;
|
||||
ev.code = eventData[i].code;
|
||||
ev.value = eventData[i].value;
|
||||
|
||||
if (write(fd, &ev, sizeof(struct input_event)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO consider different name in case of multitouch
|
||||
static int touch_end(int fd) {
|
||||
struct input_event ev;
|
||||
int i = 0;
|
||||
const int cnt = 3;
|
||||
TEventData eventData[3] = {
|
||||
{EV_ABS, ABS_MT_TRACKING_ID, -1}, {EV_KEY, BTN_TOUCH, 0}, {EV_SYN, 0, 0}};
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
memset(&ev, 0, sizeof(struct input_event));
|
||||
ev.type = eventData[i].type;
|
||||
ev.code = eventData[i].code;
|
||||
ev.value = eventData[i].value;
|
||||
|
||||
if (write(fd, &ev, sizeof(struct input_event)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: TouchScreenDevice
|
||||
* Method: create
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_LinuxTouchScreenDevice_create(JNIEnv *env,
|
||||
jobject o,
|
||||
jint width,
|
||||
jint height) {
|
||||
int productId = 123;
|
||||
const int FAKE_VENDOR_ID = 0x453;
|
||||
const int MAX_FINGER_COUNT = 9;
|
||||
const int MAX_TRACKING_ID = 65535;
|
||||
|
||||
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret_code = 0;
|
||||
ret_code = set_bit(fd, UI_SET_EVBIT, EV_SYN);
|
||||
ret_code = set_bit(fd, UI_SET_EVBIT, EV_KEY);
|
||||
ret_code = set_bit(fd, UI_SET_KEYBIT, BTN_TOUCH);
|
||||
ret_code = set_bit(fd, UI_SET_EVBIT, EV_ABS);
|
||||
ret_code = set_bit(fd, UI_SET_ABSBIT, ABS_X);
|
||||
ret_code = set_bit(fd, UI_SET_ABSBIT, ABS_Y);
|
||||
ret_code = set_bit(fd, UI_SET_ABSBIT, ABS_MT_SLOT);
|
||||
ret_code = set_bit(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
|
||||
ret_code = set_bit(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
|
||||
ret_code = set_bit(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
|
||||
ret_code = set_bit(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
|
||||
|
||||
if (ret_code < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uinput_user_dev virtual_touch_device;
|
||||
memset(&virtual_touch_device, 0, sizeof(virtual_touch_device));
|
||||
snprintf(virtual_touch_device.name, UINPUT_MAX_NAME_SIZE,
|
||||
"Virtual Touch Device - %#x", productId);
|
||||
virtual_touch_device.id.bustype = BUS_VIRTUAL;
|
||||
virtual_touch_device.id.vendor = FAKE_VENDOR_ID;
|
||||
virtual_touch_device.id.product = productId;
|
||||
virtual_touch_device.id.version = 1;
|
||||
|
||||
virtual_touch_device.absmin[ABS_X] = 0;
|
||||
virtual_touch_device.absmax[ABS_X] = width;
|
||||
virtual_touch_device.absmin[ABS_Y] = 0;
|
||||
virtual_touch_device.absmax[ABS_Y] = height;
|
||||
virtual_touch_device.absmin[ABS_MT_SLOT] = 0;
|
||||
virtual_touch_device.absmax[ABS_MT_SLOT] = MAX_FINGER_COUNT;
|
||||
virtual_touch_device.absmin[ABS_MT_POSITION_X] = 0;
|
||||
virtual_touch_device.absmax[ABS_MT_POSITION_X] = width;
|
||||
virtual_touch_device.absmin[ABS_MT_POSITION_Y] = 0;
|
||||
virtual_touch_device.absmax[ABS_MT_POSITION_Y] = height;
|
||||
virtual_touch_device.absmin[ABS_MT_TRACKING_ID] = 0;
|
||||
virtual_touch_device.absmax[ABS_MT_TRACKING_ID] = MAX_TRACKING_ID;
|
||||
|
||||
ret_code = write(fd, &virtual_touch_device, sizeof(virtual_touch_device));
|
||||
ret_code = ioctl(fd, UI_DEV_CREATE);
|
||||
if (ret_code < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: TouchScreenDevice
|
||||
* Method: destroy
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_LinuxTouchScreenDevice_destroy(JNIEnv *env,
|
||||
jobject o,
|
||||
jint fd) {
|
||||
if (ioctl(fd, UI_DEV_DESTROY) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: TouchScreenDevice
|
||||
* Method: clickImpl
|
||||
* Signature: (IIII)V
|
||||
*/
|
||||
// TODO return code with checked exception
|
||||
JNIEXPORT jint JNICALL Java_LinuxTouchScreenDevice_clickImpl(
|
||||
JNIEnv *env, jobject o, jint fd, jint trackingId, jint x, jint y) {
|
||||
touch_begin(fd, trackingId, x, y);
|
||||
touch_end(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: TouchScreenDevice
|
||||
* Method: moveImpl
|
||||
* Signature: (IIIIII)V
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_LinuxTouchScreenDevice_moveImpl(
|
||||
JNIEnv *env, jobject o, jint fd, jint trackingId, jint fromX, jint fromY,
|
||||
jint toX, jint toY) {
|
||||
touch_begin(fd, trackingId, fromX, fromY);
|
||||
touch_update(fd, toX, toY);
|
||||
touch_end(fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <WinUser.h>
|
||||
|
||||
POINTER_TOUCH_INFO create_touch_info()
|
||||
{
|
||||
POINTER_TOUCH_INFO contact;
|
||||
InitializeTouchInjection(1, TOUCH_FEEDBACK_DEFAULT); // Number of contact point
|
||||
memset(&contact, 0, sizeof(POINTER_TOUCH_INFO));
|
||||
|
||||
contact.touchFlags = TOUCH_FLAG_NONE;
|
||||
contact.touchMask = TOUCH_MASK_CONTACTAREA | TOUCH_MASK_ORIENTATION | TOUCH_MASK_PRESSURE;
|
||||
contact.orientation = 90; // Orientation of 90 means touching perpendicular to screen.
|
||||
contact.pressure = 32000;
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
void set_contact_area(POINTER_TOUCH_INFO *contact)
|
||||
{
|
||||
// 4 x 4 pixel contact area
|
||||
contact->rcContact.top = contact->pointerInfo.ptPixelLocation.y - 2;
|
||||
contact->rcContact.bottom = contact->pointerInfo.ptPixelLocation.y + 2;
|
||||
contact->rcContact.left = contact->pointerInfo.ptPixelLocation.x - 2;
|
||||
contact->rcContact.right = contact->pointerInfo.ptPixelLocation.x + 2;
|
||||
}
|
||||
|
||||
void touchBegin(POINTER_TOUCH_INFO* contact, LONG x, LONG y)
|
||||
{
|
||||
contact->pointerInfo.pointerType = PT_TOUCH;
|
||||
// primary finger pointerId == 0
|
||||
contact->pointerInfo.pointerId = 0;
|
||||
contact->pointerInfo.ptPixelLocation.x = x;
|
||||
contact->pointerInfo.ptPixelLocation.y = y;
|
||||
set_contact_area(contact);
|
||||
|
||||
contact->pointerInfo.pointerFlags = POINTER_FLAG_DOWN | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT;
|
||||
InjectTouchInput(1, contact);
|
||||
}
|
||||
|
||||
void touchUpdate(POINTER_TOUCH_INFO* contact, LONG x, LONG y)
|
||||
{
|
||||
contact->pointerInfo.pointerFlags = POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT;
|
||||
contact->pointerInfo.ptPixelLocation.x = x;
|
||||
contact->pointerInfo.ptPixelLocation.y = y;
|
||||
InjectTouchInput(1, contact);
|
||||
}
|
||||
|
||||
void touchEnd(POINTER_TOUCH_INFO* contact)
|
||||
{
|
||||
contact->pointerInfo.pointerFlags = POINTER_FLAG_UP;
|
||||
InjectTouchInput(1, contact);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: quality_util_WindowsTouchRobot
|
||||
* Method: clickImpl
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_WindowsTouchRobot_clickImpl(JNIEnv* env, jobject o,
|
||||
jint x, jint y)
|
||||
{
|
||||
POINTER_TOUCH_INFO contact = create_touch_info();
|
||||
touchBegin(&contact, x, y);
|
||||
touchEnd(&contact);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: quality_util_WindowsTouchRobot
|
||||
* Method: moveImpl
|
||||
* Signature: (IIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_WindowsTouchRobot_moveImpl(JNIEnv* env, jobject o,
|
||||
jint fromX, jint fromY,
|
||||
jint toX, jint toY)
|
||||
{
|
||||
POINTER_TOUCH_INFO contact = create_touch_info();
|
||||
touchBegin(&contact, fromX, fromY);
|
||||
touchUpdate(&contact, toX, toY);
|
||||
touchEnd(&contact);
|
||||
}
|
||||
140
test/jdk/jb/java/jcef/JBCefApp.java
Normal file
140
test/jdk/jb/java/jcef/JBCefApp.java
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
import org.cef.CefApp;
|
||||
import org.cef.CefClient;
|
||||
import org.cef.CefSettings;
|
||||
import org.cef.handler.CefAppHandlerAdapter;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @author Anton Tarasov
|
||||
*/
|
||||
public abstract class JBCefApp {
|
||||
public static class OS {
|
||||
public static final boolean WINDOWS;
|
||||
public static final boolean LINUX;
|
||||
public static final boolean MAC;
|
||||
public static final boolean UNKNOWN;
|
||||
|
||||
static {
|
||||
String name = System.getProperty("os.name").toLowerCase();
|
||||
WINDOWS = name.contains("windows");
|
||||
LINUX = name.contains("linux");
|
||||
MAC = name.contains("mac") || name.contains("darwin");
|
||||
UNKNOWN = !(WINDOWS || LINUX || MAC);
|
||||
}
|
||||
}
|
||||
|
||||
private static JBCefApp INSTANCE;
|
||||
private final CefApp myCefApp;
|
||||
|
||||
private static final AtomicBoolean ourInitialized = new AtomicBoolean(false);
|
||||
|
||||
private JBCefApp() {
|
||||
if (!CefApp.startup()) {
|
||||
throw new RuntimeException("JCEF startup failed!");
|
||||
}
|
||||
CefSettings settings = new CefSettings();
|
||||
settings.windowless_rendering_enabled = false;
|
||||
settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_ERROR;
|
||||
String[] appArgs = applyPlatformSettings(settings);
|
||||
CefApp.addAppHandler(new CefAppHandlerAdapter(appArgs) {});
|
||||
myCefApp = CefApp.getInstance(settings);
|
||||
}
|
||||
|
||||
public static JBCefApp getInstance() {
|
||||
if (!ourInitialized.getAndSet(true)) {
|
||||
if (OS.MAC) {
|
||||
INSTANCE = new JBCefAppMac();
|
||||
}
|
||||
else if (OS.LINUX) {
|
||||
INSTANCE = new JBCefAppLinux();
|
||||
}
|
||||
else if (OS.WINDOWS) {
|
||||
INSTANCE = new JBCefAppWindows();
|
||||
}
|
||||
else {
|
||||
INSTANCE = null;
|
||||
assert false : "JBCefApp platform initialization failed";
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
protected abstract String[] applyPlatformSettings(CefSettings settings);
|
||||
|
||||
private static class JBCefAppMac extends JBCefApp {
|
||||
@Override
|
||||
protected String[] applyPlatformSettings(CefSettings settings) {
|
||||
String ALT_CEF_FRAMEWORK_DIR = System.getenv("ALT_CEF_FRAMEWORK_DIR");
|
||||
String ALT_CEF_HELPER_DIR = System.getenv("ALT_CEF_HELPER_DIR");
|
||||
if (ALT_CEF_FRAMEWORK_DIR == null || ALT_CEF_HELPER_DIR == null) {
|
||||
String CONTENTS_PATH = System.getProperty("java.home") + "/..";
|
||||
if (ALT_CEF_FRAMEWORK_DIR == null) {
|
||||
ALT_CEF_FRAMEWORK_DIR = CONTENTS_PATH + "/Frameworks/Chromium Embedded Framework.framework";
|
||||
}
|
||||
if (ALT_CEF_HELPER_DIR == null) {
|
||||
ALT_CEF_HELPER_DIR = CONTENTS_PATH + "/Helpers";
|
||||
}
|
||||
}
|
||||
return new String[] {
|
||||
"--framework-dir-path=" + normalize(ALT_CEF_FRAMEWORK_DIR),
|
||||
"--browser-subprocess-path=" + normalize(ALT_CEF_HELPER_DIR) + "/jcef Helper.app/Contents/MacOS/jcef Helper",
|
||||
"--disable-in-process-stack-traces"
|
||||
};
|
||||
}
|
||||
|
||||
// CEF does not accept ".." in path
|
||||
static String normalize(String path) {
|
||||
try {
|
||||
return new File(path).getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class JBCefAppWindows extends JBCefApp {
|
||||
@Override
|
||||
protected String[] applyPlatformSettings(CefSettings settings) {
|
||||
String JCEF_PATH = System.getProperty("java.home") + "/bin";
|
||||
settings.resources_dir_path = JCEF_PATH;
|
||||
settings.locales_dir_path = JCEF_PATH + "/locales";
|
||||
settings.browser_subprocess_path = JCEF_PATH + "/jcef_helper";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class JBCefAppLinux extends JBCefApp {
|
||||
@Override
|
||||
protected String[] applyPlatformSettings(CefSettings settings) {
|
||||
String JCEF_PATH = System.getProperty("java.home") + "/lib";
|
||||
settings.resources_dir_path = JCEF_PATH;
|
||||
settings.locales_dir_path = JCEF_PATH + "/locales";
|
||||
settings.browser_subprocess_path = JCEF_PATH + "/jcef_helper";
|
||||
return new String[] {
|
||||
"--force-device-scale-factor=" + sysScale()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public CefClient createClient() {
|
||||
return myCefApp.createClient();
|
||||
}
|
||||
|
||||
public CefApp getCefApp() {
|
||||
return myCefApp;
|
||||
}
|
||||
|
||||
public static double sysScale() {
|
||||
try {
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform().getScaleX();
|
||||
} catch (NullPointerException ignore) {}
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import org.cef.CefApp;
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
import org.cef.CefClient;
|
||||
import org.cef.CefSettings;
|
||||
import org.cef.browser.CefBrowser;
|
||||
import org.cef.browser.CefFrame;
|
||||
import org.cef.handler.CefAppHandlerAdapter;
|
||||
import org.cef.handler.CefLoadHandlerAdapter;
|
||||
import org.cef.network.CefRequest;
|
||||
|
||||
@@ -20,30 +19,11 @@ import java.util.concurrent.TimeUnit;
|
||||
* @run main JCEFStartupTest
|
||||
*/
|
||||
public class JCEFStartupTest {
|
||||
static final CefApp CEF_APP;
|
||||
static final CefClient CEF_CLIENT;
|
||||
static CefClient CEF_CLIENT = JBCefApp.getInstance().createClient();
|
||||
|
||||
static final CountDownLatch LATCH = new CountDownLatch(1);
|
||||
static volatile boolean PASSED;
|
||||
|
||||
static {
|
||||
CefSettings settings = new CefSettings();
|
||||
settings.windowless_rendering_enabled = false;
|
||||
settings.background_color = settings.new ColorType(255, 0, 255, 0);
|
||||
settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_ERROR;
|
||||
CefApp.startup();
|
||||
|
||||
String JCEF_FRAMEWORKS_PATH = System.getProperty("java.home") + "/Frameworks";
|
||||
CefApp.addAppHandler(new CefAppHandlerAdapter(new String[] {
|
||||
"--framework-dir-path=" + JCEF_FRAMEWORKS_PATH + "/Chromium Embedded Framework.framework",
|
||||
"--browser-subprocess-path=" + JCEF_FRAMEWORKS_PATH + "/jcef Helper.app/Contents/MacOS/jcef Helper",
|
||||
"--disable-in-process-stack-traces"
|
||||
}) {});
|
||||
|
||||
CEF_APP = CefApp.getInstance(settings);
|
||||
CEF_CLIENT = CEF_APP.createClient();
|
||||
}
|
||||
|
||||
JCEFStartupTest() {
|
||||
JFrame frame = new JFrame("JCEF");
|
||||
|
||||
@@ -85,7 +65,7 @@ public class JCEFStartupTest {
|
||||
}
|
||||
|
||||
CEF_CLIENT.dispose();
|
||||
CEF_APP.dispose();
|
||||
JBCefApp.getInstance().getCefApp().dispose();
|
||||
|
||||
if (!PASSED) {
|
||||
throw new RuntimeException("Test FAILED!");
|
||||
|
||||
@@ -146,7 +146,7 @@ java/awt/EventQueue/6980209/bug6980209.java
|
||||
java/awt/FileDialog/8003399/bug8003399.java 8198334 windows-all
|
||||
java/awt/FileDialog/FileDialogIconTest/FileDialogIconTest.java 8160558 windows-all
|
||||
java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.html 8202882 linux-all
|
||||
java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all
|
||||
java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all,macosx-all
|
||||
java/awt/Focus/8013611/JDK8013611.java 8175366,8213522 windows-all,macosx-all,linux-all
|
||||
java/awt/Focus/6378278/InputVerifierTest.java 8198616,8047703 macosx-all,linux-4.15,windows-all
|
||||
java/awt/Focus/6382144/EndlessLoopTest.java 8198617,8047703 generic-all
|
||||
@@ -197,7 +197,6 @@ java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java
|
||||
java/awt/FontMetrics/FontCrash.java 8198336 windows-all
|
||||
java/awt/FontMetrics/MaxAdvanceIsMax.java 8221304 solaris-all,macosx-all
|
||||
java/awt/Frame/DisposeParentGC/DisposeParentGC.java 8079786,8055833 macosx-all,linux-all
|
||||
java/awt/Frame/DisposeStressTest/DisposeStressTest.html JBR-1905 macosx-all
|
||||
java/awt/Frame/ExceptionOnSetExtendedStateTest/ExceptionOnSetExtendedStateTest.java 8198237 macosx-all
|
||||
java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all
|
||||
java/awt/Frame/FrameLocation/FrameLocation.java 8019803 macosx-all
|
||||
@@ -559,7 +558,7 @@ java/awt/Paint/PaintNativeOnUpdate.java
|
||||
java/awt/Paint/bug8024864.java 8176512 windows-all,macosx-all,linux-all
|
||||
java/awt/PrintJob/PrinterException.java 8194045 generic-all
|
||||
java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all,windows-all
|
||||
java/awt/Robot/CheckCommonColors/CheckCommonColors.java 8215105 macosx-all
|
||||
java/awt/Robot/CheckCommonColors/CheckCommonColors.java 8237925 macosx-all,windows-all,linux-all
|
||||
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java 8215105 macosx-all,windows-all
|
||||
java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java 8157173 generic-all
|
||||
java/awt/Robot/RobotWheelTest/RobotWheelTest.java 8129827 generic-all
|
||||
@@ -568,10 +567,8 @@ java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java
|
||||
java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java 8061235,8159592,8134231 macosx-all,windows-all,linux-all
|
||||
java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all
|
||||
java/awt/TextArea/AutoScrollOnSelectAndAppend/AutoScrollOnSelectAndAppend.java 8213120 macosx-all,linux-all, windows-all (windows, linux - time out)
|
||||
java/awt/TextArea/DisposeTest/TestDispose.java JBR-1905 generic-all
|
||||
java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java 8196300 windows-all
|
||||
java/awt/TextField/SelectionInvisibleTest/SelectionInvisibleTest.java 8169533 macosx-all,windows-all
|
||||
java/awt/TextField/DisposeTest/TestDispose.java JBR-1905 macosx-all
|
||||
java/awt/Toolkit/DesktopProperties/rfe4758438.java 8193547 linux-all
|
||||
java/awt/Toolkit/LockingKeyStateTest/LockingKeyStateTest.java 8208514 windows-all
|
||||
java/awt/Toolkit/RealSync/Test.java 6849383 generic-all
|
||||
@@ -596,6 +593,7 @@ java/awt/Window/BackgroundIsNotUpdated/BackgroundIsNotUpdated.java
|
||||
java/awt/Window/Grab/GrabTest.java 8196019 macosx-all,windows-all,linux-all
|
||||
java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java 8215132,8194941 macosx-all,windows-all,linux-all
|
||||
java/awt/Window/MultiWindowApp/MultiWindowAppTest.java 8159904 macosx-all,windows-all,linux-all
|
||||
java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java 8225116 windows-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/FocusAWTTest.java 8061236 macosx-all,windows-all,linux-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/SetShape.java 8208509 macosx-all,windows-all,linux-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/SetShapeAndClick.java 8197936 macosx-all,windows-all,linux-4.18.16-200.fc28.x86_64,linux-all (linux-all timeout reproduced with Adopt)
|
||||
@@ -674,6 +672,7 @@ java/awt/image/DrawImage/IncorrectDestinationOffset.java
|
||||
java/awt/image/DrawImage/IncorrectSourceOffset.java 8196086 windows-all
|
||||
java/awt/image/DrawImage/IncorrectUnmanagedImageRotatedClip.java 8196087 windows-all
|
||||
java/awt/image/MultiResolutionImage/MultiResolutionDrawImageWithTransformTest.java 8198390 generic-all
|
||||
java/awt/image/multiresolution/MenuMultiresolutionIconTest.java 8151301 macosx-all,windows-all (windows - nobug commit testing)
|
||||
java/awt/image/multiresolution/MultiresolutionIconTest.java 8169187 macosx-all,linux-all,windows-all
|
||||
java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8204214,8193941 macosx-all,windows-all,linux-all
|
||||
java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all
|
||||
@@ -831,6 +830,7 @@ sun/security/pkcs11/tls/TestKeyMaterial.java
|
||||
sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8209398 generic-all
|
||||
|
||||
security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/LuxTrustCA.java 8237888 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
@@ -941,7 +941,7 @@ javax/swing/JPopupMenu/6987844/bug6987844.java
|
||||
javax/swing/JPopupMenu/7156657/bug7156657.java 8171381 macosx-all,windows-all
|
||||
javax/swing/JPopupMenu/8075063/ContextMenuScrollTest.java 8202880 linux-all,windows-all,macosx-all
|
||||
javax/swing/JRadioButton/8033699/bug8033699.java 8197552,8064920 macosx-all,windows-all,linux-all
|
||||
javax/swing/JRadioButton/8041561/bug8041561.java 8194941 linux-all
|
||||
javax/swing/JRadioButton/8041561/bug8041561.java 8194941,8233555 linux-all,macosx-all,windows-all (windows - nobug commit testing)
|
||||
javax/swing/JRadioButton/8075609/bug8075609.java 8197552 macosx-all,windows-all,linux-all
|
||||
javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java 8197552 macosx-all,windows-all,linux-all
|
||||
javax/swing/JRadioButton/FocusTraversal/FocusTraversal.java 8221902 windows-all,linux-all (windows: commit testing)
|
||||
@@ -1039,7 +1039,7 @@ javax/swing/text/TableView/TableViewLayoutTest.java
|
||||
javax/swing/text/Utilities/8134721/bug8134721.java 8199062 generic-all
|
||||
javax/swing/text/Utilities/8142966/SwingFontMetricsTest.java 8199529 windows-all
|
||||
javax/swing/text/View/8014863/bug8014863.java 8072110 windows-all,linux-all
|
||||
javax/swing/text/html/CSS/4530474/bug4530474.java 8194941 linux-all
|
||||
javax/swing/text/html/CSS/4530474/bug4530474.java 8194941,8151301 linux-all,macosx-all,windows-all (windows - nobug commit testing)
|
||||
javax/swing/text/html/HTMLEditorKit/5043626/bug5043626.java 8072110 windows-all,linux-all
|
||||
javax/swing/text/html/StyleSheet/BackgroundImage/BackgroundImagePosition.java 8198409 generic-all
|
||||
javax/swing/text/html/StyleSheet/bug4936917.java 8208569 macosx-all
|
||||
@@ -1249,4 +1249,5 @@ javax/swing/LookAndFeel/8145547/DemandGTK.java
|
||||
javax/swing/LookAndFeel/8146276/NimbusGlueTest.java JBR-1977 linux-aarch64
|
||||
sanity/client/SwingSet/src/GridBagLayoutDemoTest.java JBR-1977 linux-aarch64
|
||||
|
||||
jb/java/jcef/JCEFStartupTest.java JBR-2094 macosx-all
|
||||
jb/java/jcef/JCEFStartupTest.java JBR-1996,JBR-2094 macosx-all,linux-i386,windows-x86
|
||||
jb/java/awt/event/TouchScreenEvent/TouchScreenEventsTest.java nobug windows-6.1 not supported on Windows 7
|
||||
|
||||
@@ -32,6 +32,7 @@ java/awt/Focus/RequestFocusAndHideTest/RequestFocusAndHideTest.java
|
||||
java/awt/Focus/RequestFocusByCause/RequestFocusByCauseTest.java nobug linux-all,macosx-all,windows-all reproduced with Adopt, OpenJDK
|
||||
java/awt/Focus/WindowIsFocusableAccessByThreadsTest/WindowIsFocusableAccessByThreadsTest.java nobug macosx-all,windows-all
|
||||
java/awt/Frame/8158918/SetExtendedState.java nobug linux-all
|
||||
java/awt/Frame/DisposeStressTest/DisposeStressTest.html JBR-1905 macosx-all
|
||||
java/awt/Frame/FrameLocation/FrameLocation.java nobug linux-all
|
||||
java/awt/Frame/FrameSize/TestFrameSize.java nobug linux-all,mac-osx
|
||||
java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java nobug linux-all,windows-all
|
||||
@@ -144,7 +145,6 @@ java/awt/image/VolatileImage/DrawBufImgOp.java
|
||||
java/awt/image/VolatileImage/DrawHugeImageTest.java nobug windows-all
|
||||
java/awt/image/VolatileImage/TransparentVImage.java nobug windows-all
|
||||
java/awt/image/multiresolution/Corrupted2XImageTest.java nobug macosx-all
|
||||
java/awt/image/multiresolution/MenuMultiresolutionIconTest.java nobug macosx-all,windows-all
|
||||
java/awt/keyboard/AltPlusNumberKeyCombinationsTest/AltPlusNumberKeyCombinationsTest.java nobug windows-all
|
||||
java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java nobug windows-all,linux-all
|
||||
|
||||
@@ -179,7 +179,6 @@ javax/swing/JPopupMenu/6544309/bug6544309.java
|
||||
javax/swing/JPopupMenu/6691503/bug6691503.java nobug macosx-all
|
||||
javax/swing/JPopupMenu/6827786/bug6827786.java nobug windows-all
|
||||
javax/swing/JProgressBar/8015748/JProgressBarOrientationRobotTest.java nobug macosx-all,windows-all
|
||||
javax/swing/JRadioButton/8041561/bug8041561.java nobug windows-all
|
||||
javax/swing/JScrollBar/7163696/Test7163696.java nobug windows-all
|
||||
javax/swing/JScrollBar/bug4202954/bug4202954.java nobug generic-all timeout
|
||||
javax/swing/JSlider/6401380/bug6401380.java nobug windows-all
|
||||
@@ -209,7 +208,6 @@ javax/swing/reliability/TaskZoomJFrameChangeState.java
|
||||
javax/swing/reliability/TaskZoomJFrameRepaint.java nobug linux-all,windows-all
|
||||
javax/swing/text/Caret/TestCaretPosition.java nobug linux-all
|
||||
javax/swing/text/FlowView/LayoutTest.java nobug windows-all
|
||||
javax/swing/text/html/CSS/4530474/bug4530474.java nobug windows-all
|
||||
javax/swing/text/html/StyleSheet/bug4936917.java nobug macosx-all,windows-all
|
||||
|
||||
jb/javax/swing/JDialog/JDialog186.java nobug macosx-all,linux-all,windows-all
|
||||
|
||||
Reference in New Issue
Block a user