Compare commits

..

17 Commits

Author SHA1 Message Date
Alexander Lobas
e5d96e6747 JBR-4834 Rounded corners on Mac OS: support custom border color 2022-09-20 16:05:26 +02:00
Alexander Lobas
995841e5e3 JBR-4834 Rounded corners on Mac OS: support custom border color 2022-09-20 16:05:26 +02:00
Alexander Lobas
008b01e11d JBR-4834 Rounded corners on Mac OS: support custom border color 2022-09-20 16:05:26 +02:00
Vitaly Provodin
88e71f2056 JBR-4814 fix paths passing to --with-extra-cflags, --with-extra-cxxflags, --with-extra-ldflags params 2022-09-19 15:14:11 +07:00
Vitaly Provodin
867686a430 Update README.md 2022-09-16 11:06:23 +07:00
Nikita Gubarkov
1855d8955c JBR-3677 Change copyright for CustomTitleBarDoubleClick test 2022-09-15 23:04:37 +03:00
Alexey Ushakov
8a14c80209 JBR-4696 macOS: NPE in -[AWTView viewDidChangeBackingProperties]
Added null pointer checks
2022-09-15 21:16:20 +02:00
Nikita Gubarkov
c7d906e7c7 JBR-3677 Add CustomTitleBarDoubleClick test 2022-09-15 19:40:38 +03:00
Nikita Gubarkov
a9475c85cd JBR-3677 check AppleActionOnDoubleClick property for custom window decorations on macOS 2022-09-15 17:11:31 +03:00
Maxim Kartashev
1f9cdefaef JBR-4626 MacOS aarch64: SIGSEGV at RenderCache.get / ScaledBlit.getFromCache
Avoid C2-compiled loop crashes by replacing the handcrafted MRU cache
with a more modern LinkedHashMap-based one.
2022-09-15 11:26:23 +03:00
Alexey Ushakov
5e5239464a JBR-4588 macOS: SIGILL at [libsystem_kernel] __kill in CCE: class sun.java2d.opengl.CGLGraphicsConfig cannot be cast to class sun.java2d.metal.MTLGraphicsConfig
Moved tryLoadMetalLibrary under RQ lock.
Added more diagnostics.
2022-09-14 19:46:21 +02:00
Alexey Ushakov
62a3f98138 JBR-4680 idea window flickers while changing the screen brightness
Update insets in separate notification
2022-09-14 19:11:51 +02:00
Nikita Gubarkov
cea6ac1be5 JBR-4816 Don't test RoundedCornersManager on Linux 2022-09-14 18:12:19 +03:00
Dmitry Batrak
a170b4e4ae JBR-4820 Focus lost after showing popup and context menu - missing changes
missing reverts
2022-09-14 13:18:02 +03:00
Dmitry Batrak
c9609330f2 JBR-4820 Focus lost after showing popup and context menu 2022-09-14 09:34:21 +03:00
Vitaly Provodin
1750c6f390 exclude java/awt/Modal/ModalInternalFrameTest/ModalInternalFrameTest.java on Linux because of 8159599 2022-09-13 07:19:25 +07:00
Vitaly Provodin
fb725c15c4 JBR-893 exclude failing tests 2022-09-12 05:28:10 +07:00
25 changed files with 541 additions and 176 deletions

View File

@@ -11,6 +11,7 @@ can be found on the [releases page](https://github.com/JetBrains/JetBrainsRuntim
| IDE Version | Latest JBR | Date Released |
| --- | --- | --- |
| 2022.3 | [17.0.4.1-b597.1](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.4.1b597.1)| 12-Sep-2022 |
| 2022.2 | [17.0.4-b469.53](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.4b469.53)| 31-Aug-2022 |

View File

@@ -29,6 +29,14 @@ BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)}
function do_configure {
if [[ "${architecture}" == *aarch64* ]]; then
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
WITH_EXTRA_CFLAGS="--with-extra-cflags="-F$(pwd)/$JCEF_PATH/Frameworks"
--with-extra-cxxflags="-F$(pwd)/$JCEF_PATH/Frameworks"
--with-extra-ldflags="-F$(pwd)/$JCEF_PATH/Frameworks" "
else
WITH_EXTRA_CFLAGS=""
fi
sh configure \
$WITH_DEBUG_LEVEL \
--with-vendor-name="${VENDOR_NAME}" \
@@ -43,9 +51,7 @@ function do_configure {
--with-macosx-version-max="${MACOSX_VERSION_MAX:="11.00.00"}" \
--disable-hotspot-gtest --disable-javac-server --disable-full-docs --disable-manpages \
--enable-cds=no \
--with-extra-cflags="-F$(pwd)/Frameworks" \
--with-extra-cxxflags="-F$(pwd)/Frameworks" \
--with-extra-ldflags="-F$(pwd)/Frameworks" \
$WITH_EXTRA_CFLAGS \
$STATIC_CONF_ARGS \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \

View File

@@ -66,8 +66,11 @@ import java.util.Map;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.util.logging.PlatformLogger;
class _AppEventHandler {
private static final PlatformLogger logger = PlatformLogger.getLogger(_AppEventHandler.class.getName());
private static final int NOTIFY_ABOUT = 1;
private static final int NOTIFY_PREFS = 2;
private static final int NOTIFY_OPEN_APP = 3;
@@ -267,10 +270,13 @@ class _AppEventHandler {
instance.systemSleepDispatcher.dispatch(new _NativeEvent(Boolean.FALSE));
break;
case NOTIFY_SCREEN_CHANGE_PARAMETERS:
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("NOTIFY_SCREEN_CHANGE_PARAMETERS");
}
if (AppContext.getAppContext() != null) {
EventQueue.invokeLater(
() -> ((SunGraphicsEnvironment)SunGraphicsEnvironment.
getLocalGraphicsEnvironment()).displayChanged());
getLocalGraphicsEnvironment()).displayParametersChanged());
}
break;
default:

View File

@@ -46,7 +46,7 @@ import sun.util.logging.PlatformLogger;
import static java.awt.peer.ComponentPeer.SET_BOUNDS;
public final class CGraphicsDevice extends GraphicsDevice
implements DisplayChangedListener {
implements DisplayChangedListener, DisplayParametersChangedListener {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGraphicsDevice.class.getName());
/**
@@ -74,11 +74,12 @@ public final class CGraphicsDevice extends GraphicsDevice
public CGraphicsDevice(final int displayID) {
this.displayID = displayID;
this.initialMode = getDisplayMode();
StringBuilder errorMessage = new StringBuilder();
if (MacOSFlags.isMetalEnabled()) {
// Try to create MTLGraphicsConfig, if it fails,
// try to create CGLGraphicsConfig as a fallback
this.config = MTLGraphicsConfig.getConfig(this, displayID);
this.config = MTLGraphicsConfig.getConfig(this, displayID, errorMessage);
if (this.config != null) {
metalPipelineEnabled = true;
@@ -88,7 +89,7 @@ public final class CGraphicsDevice extends GraphicsDevice
// Should not fall back to OpenGL if Metal has been used before
// (it could cause CCE during replace of surface data)
throw new InternalError("Error - unable to initialize Metal" +
" after recreation of graphics device.");
" after recreation of graphics device." + errorMessage);
}
// Try falling back to OpenGL pipeline
@@ -119,7 +120,7 @@ public final class CGraphicsDevice extends GraphicsDevice
" rendering pipeline");
}
this.config = MTLGraphicsConfig.getConfig(this, displayID);
this.config = MTLGraphicsConfig.getConfig(this, displayID, errorMessage);
if (this.config != null) {
metalPipelineEnabled = true;
@@ -131,7 +132,7 @@ public final class CGraphicsDevice extends GraphicsDevice
// This indicates fallback to other rendering pipeline also failed.
// Should never reach here
throw new InternalError("Error - unable to initialize any" +
" rendering pipeline.");
" rendering pipeline." + errorMessage);
}
if (metalPipelineEnabled && MacOSFlags.isMetalVerbose()) {
@@ -223,6 +224,20 @@ public final class CGraphicsDevice extends GraphicsDevice
//TODO configs?
}
public void displayParametersChanged() {
Insets newScreenInsets = nativeGetScreenInsets(displayID);
if (!newScreenInsets.equals(screenInsets)) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Screen insets for display(" + displayID + ") changed " +
"[top=" + screenInsets.top + ",left=" + screenInsets.left +
",bottom=" + screenInsets.bottom + ",right=" + screenInsets.right +
"]->[top=" + newScreenInsets.top + ",left=" + newScreenInsets.left +
",bottom=" + newScreenInsets.bottom + ",right=" + newScreenInsets.right +
"]");
}
screenInsets = newScreenInsets;
}
}
@Override
public void paletteChanged() {
// devices do not need to react to this event.

View File

@@ -25,6 +25,7 @@
package sun.java2d.metal;
import java.lang.annotation.Native;
import sun.awt.CGraphicsConfig;
import sun.awt.CGraphicsDevice;
import sun.awt.image.OffScreenImage;
@@ -72,6 +73,11 @@ import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_BIOP_SHADER;
public final class MTLGraphicsConfig extends CGraphicsConfig
implements AccelGraphicsConfig, SurfaceManager.ProxiedGraphicsConfig
{
@Native private final static int LOAD_LIB_ERROR = -1;
@Native private final static int LOAD_LIB_OK = 0;
@Native private final static int LOAD_LIB_NO_DEVICE = 1;
@Native private final static int LOAD_LIB_NO_SHADER_LIB = 2;
private static boolean mtlAvailable;
private static boolean mtlUsed = false;
private static ImageCapabilities imageCaps = new MTLImageCaps();
@@ -91,7 +97,7 @@ public final class MTLGraphicsConfig extends CGraphicsConfig
private final int maxTextureSize;
private static native boolean isMetalFrameworkAvailable();
private static native boolean tryLoadMetalLibrary(int displayID, String shaderLib);
private static native int tryLoadMetalLibrary(int displayID, String shaderLib);
private static native long getMTLConfigInfo(int displayID, String mtlShadersLib);
/**
@@ -132,21 +138,29 @@ public final class MTLGraphicsConfig extends CGraphicsConfig
}
public static MTLGraphicsConfig getConfig(CGraphicsDevice device,
int displayID)
int displayID, StringBuilder errorMessage)
{
if (!mtlAvailable) {
return null;
}
if (!tryLoadMetalLibrary(displayID, mtlShadersLib)) {
return null;
}
long cfginfo = 0;
int textureSize = 0;
MTLRenderQueue rq = MTLRenderQueue.getInstance();
rq.lock();
try {
int res = tryLoadMetalLibrary(displayID, mtlShadersLib);
if (res != LOAD_LIB_OK) {
errorMessage.append(" Cannot load metal library: " +
switch (res) {
case LOAD_LIB_ERROR -> "Unexpected error.";
case LOAD_LIB_NO_DEVICE -> "No MTLDevice.";
case LOAD_LIB_NO_SHADER_LIB -> "No Metal shader library.";
default -> throw new IllegalStateException("Unexpected value: " + res);
});
return null;
}
cfginfo = getMTLConfigInfo(displayID, mtlShadersLib);
if (cfginfo != 0L) {
textureSize = nativeGetMaxTextureSize();
@@ -160,6 +174,7 @@ public final class MTLGraphicsConfig extends CGraphicsConfig
rq.unlock();
}
if (cfginfo == 0) {
errorMessage.append(" Cannot create MTLConfigInfo.");
return null;
}

View File

@@ -214,7 +214,7 @@ public class CPlatformView extends CFRetainedResource {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Changed backing properties, scale = " + scale);
}
if (scale > 0) {
if (scale > 0 && windowLayer != null) {
windowLayer.replaceSurfaceData(Math.round(scale));
}
}

View File

@@ -107,7 +107,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private static native void nativeRaiseLevel(long nsWindowPtr, boolean popup, boolean onlyIfParentIsActive);
private static native void nativeSetTransparentTitleBarHeight(long nsWindowPtr, float height);
private static native void nativeCallDeliverMoveResizeEvent(long nsWindowPtr);
private static native void nativeSetRoundedCorners(long nsWindowPrt, float radius);
private static native void nativeSetRoundedCorners(long nsWindowPrt, float radius, int borderWidth, int borderColor);
// Loger to report issues happened during execution but that do not affect functionality
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
@@ -1531,7 +1531,13 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private void setRoundedCorners(Object params) {
if (params instanceof Float) {
execute(ptr -> nativeSetRoundedCorners(ptr, (float) params));
execute(ptr -> nativeSetRoundedCorners(ptr, (float) params, 0, 0));
} else if (params instanceof Object[]) {
Object[] values = (Object[]) params;
if (values.length == 3 && values[0] instanceof Float && values[1] instanceof Integer && values[2] instanceof Color) {
Color color = (Color) values[2];
execute(ptr -> nativeSetRoundedCorners(ptr, (float) values[0], (int) values[1], color.getRGB()));
}
}
}
}

View File

@@ -1519,6 +1519,9 @@ static jclass jc_CInputMethod = NULL;
- (void)viewDidChangeBackingProperties {
JNIEnv *env = [ThreadUtilities getJNIEnv];
if ((*env)->IsSameObject(env, m_cPlatformView, NULL)) {
return;
}
static double debugScale = -2.0;
if (debugScale == -2.0) { // default debugScale value in SGE is -1.0
debugScale = JNU_CallStaticMethodByName(env, NULL, "sun/java2d/SunGraphicsEnvironment",

View File

@@ -1553,7 +1553,11 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
} else {
jint hitSpot = [self hitTestCustomDecoration:event.locationInWindow];
if (event.clickCount == 2 && hitSpot == java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT) {
[self.window performZoom:nil];
if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AppleActionOnDoubleClick"] isEqualToString:@"Maximize"]) {
[self.window performZoom:nil];
} else {
[self.window performMiniaturize:nil];
}
}
// We don't follow the regular responder chain here since the native window swallows events in some cases
@@ -2391,7 +2395,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCallDeliverMo
}
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetRoundedCorners
(JNIEnv *env, jclass clazz, jlong windowPtr, jfloat radius)
(JNIEnv *env, jclass clazz, jlong windowPtr, jfloat radius, jint borderWidth, jint borderRgb)
{
JNI_COCOA_ENTER(env);
@@ -2401,6 +2405,18 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetRoundedCor
w.contentView.wantsLayer = YES;
w.contentView.layer.cornerRadius = radius;
w.contentView.layer.masksToBounds = YES;
if (borderWidth > 0) {
CGFloat alpha = (((borderRgb >> 24) & 0xff) / 255.0);
CGFloat red = (((borderRgb >> 16) & 0xff) / 255.0);
CGFloat green = (((borderRgb >> 8) & 0xff) / 255.0);
CGFloat blue = (((borderRgb >> 0) & 0xff) / 255.0);
NSColor *color = [NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha];
w.contentView.layer.borderWidth = borderWidth;
w.contentView.layer.borderColor = color.CGColor;
}
w.backgroundColor = NSColor.clearColor;
w.opaque = NO;
// remove corner radius animation

View File

@@ -70,11 +70,11 @@ Java_sun_java2d_metal_MTLGraphicsConfig_isMetalFrameworkAvailable
return metalSupported;
}
JNIEXPORT jboolean JNICALL
JNIEXPORT jint JNICALL
Java_sun_java2d_metal_MTLGraphicsConfig_tryLoadMetalLibrary
(JNIEnv *env, jclass mtlgc, jint displayID, jstring shadersLibName)
{
__block jboolean ret = JNI_FALSE;
__block jint ret = sun_java2d_metal_MTLGraphicsConfig_LOAD_LIB_ERROR;
JNI_COCOA_ENTER(env);
@@ -87,12 +87,14 @@ JNI_COCOA_ENTER(env);
NSError* error = nil;
id<MTLLibrary> lib = [device newLibraryWithFile:path error:&error];
if (lib != nil) {
ret = JNI_TRUE;
ret = sun_java2d_metal_MTLGraphicsConfig_LOAD_LIB_OK;
} else {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_tryLoadMetalLibrary - Failed to load Metal shader library.");
ret = sun_java2d_metal_MTLGraphicsConfig_LOAD_LIB_NO_SHADER_LIB;
}
} else {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_tryLoadMetalLibrary - Failed to create MTLDevice.");
ret = sun_java2d_metal_MTLGraphicsConfig_LOAD_LIB_NO_DEVICE;
}
}];

View File

@@ -152,17 +152,6 @@ public abstract class KeyboardFocusManager
public Container getCurrentFocusCycleRoot() {
return KeyboardFocusManager.currentFocusCycleRoot;
}
@Override
public void enqueueKeyEvents(Component untilFocused) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().enqueueKeyEvents(
Toolkit.getEventQueue().getMostRecentKeyEventTime(), untilFocused);
}
@Override
public void dequeueKeyEvents(Component untilFocused) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().dequeueKeyEvents(-1, untilFocused);
}
}
);
}

View File

@@ -464,10 +464,6 @@ public final class AWTAccessor {
* Return the current focus cycle root
*/
Container getCurrentFocusCycleRoot();
void enqueueKeyEvents(Component untilFocused);
void dequeueKeyEvents(Component untilFocused);
}
/**

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, JetBrains s.r.o.. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.util.EventListener;
public interface DisplayParametersChangedListener extends EventListener {
/**
* Invoked when the display parameters changed.
*/
public void displayParametersChanged();
}

View File

@@ -50,6 +50,7 @@ import java.util.Locale;
import java.util.TreeMap;
import sun.awt.DisplayChangedListener;
import sun.awt.DisplayParametersChangedListener;
import sun.awt.SunDisplayChanger;
import sun.font.*;
import sun.java2d.pipe.Region;
@@ -64,7 +65,7 @@ import sun.security.action.GetPropertyAction;
*/
@SuppressWarnings("removal")
public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
implements DisplayChangedListener {
implements DisplayChangedListener, DisplayParametersChangedListener {
/** Establish the default font to be used by SG2D. */
private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
@@ -271,6 +272,15 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
displayChanger.notifyListeners();
}
@Override
public void displayParametersChanged() {
for (GraphicsDevice gd : getScreenDevices()) {
if (gd instanceof DisplayParametersChangedListener) {
((DisplayParametersChangedListener) gd).displayParametersChanged();
}
}
}
/**
* Part of the DisplayChangedListener interface:
* propagate this event to listeners

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,68 +25,44 @@
package sun.java2d.loops;
import java.util.LinkedHashMap;
import java.util.Map;
public final class RenderCache {
final class Entry {
private SurfaceType src;
private CompositeType comp;
private SurfaceType dst;
private Object value;
private final int MAX_ENTRIES;
private final Map<Key, Object> mruCache;
public Entry(SurfaceType src,
CompositeType comp,
SurfaceType dst,
Object value)
{
this.src = src;
this.comp = comp;
this.dst = dst;
this.value = value;
}
public boolean matches(SurfaceType src,
CompositeType comp,
SurfaceType dst)
{
// bug 4725045: using equals() causes different SurfaceType
// objects with the same strings to match in the cache, which is
// not the behavior we want. Constrain the match to succeed only
// on object matches instead.
return ((this.src == src) &&
(this.comp == comp) &&
(this.dst == dst));
}
public Object getValue() {
return value;
record Key(SurfaceType src, CompositeType comp, SurfaceType dst) {
@Override
public boolean equals(Object o) {
if (o instanceof Key other) {
// bug 4725045: using equals() causes different SurfaceType
// objects with the same strings to match in the cache, which is
// not the behavior we want. Constrain the match to succeed only
// on object matches instead.
return ((this.src == other.src) &&
(this.comp == other.comp) &&
(this.dst == other.dst));
}
return false;
}
}
private Entry[] entries;
public RenderCache(int size) {
entries = new Entry[size];
MAX_ENTRIES = size;
mruCache = new LinkedHashMap<>(size + 1) {
@Override
protected boolean removeEldestEntry(Map.Entry<Key, Object> eldest) {
return size() > MAX_ENTRIES;
}
};
}
public synchronized Object get(SurfaceType src,
CompositeType comp,
SurfaceType dst)
{
int max = entries.length - 1;
for (int i = max; i >= 0; i--) {
Entry e = entries[i];
if (e == null) {
break;
}
if (e.matches(src, comp, dst)) {
if (i < max - 4) {
System.arraycopy(entries, i+1, entries, i, max - i);
entries[max] = e;
}
return e.getValue();
}
}
return null;
return mruCache.get(new Key(src, comp, dst));
}
public synchronized void put(SurfaceType src,
@@ -94,10 +70,6 @@ public final class RenderCache {
SurfaceType dst,
Object value)
{
Entry e = new Entry(src, comp, dst, value);
int num = entries.length;
System.arraycopy(entries, 1, entries, 0, num - 1);
entries[num - 1] = e;
mruCache.put(new Key(src, comp, dst), value);
}
}

View File

@@ -293,15 +293,21 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
* when a component inside a Frame is requesting focus.
* See 6314575 for details.
*/
return wpeer.requestWindowFocus(null, () -> {
XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
target,
temporary,
focusedWindowChangeAllowed,
time, cause);
}, () -> {
rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
});
boolean res = wpeer.requestWindowFocus(null);
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
focusLog.finer("Requested window focus: " + res);
}
// If parent window can be made focused and has been made focused(synchronously)
// then we can proceed with children, otherwise we retreat.
if (!(res && parentWindow.isFocused())) {
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
}
return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
target,
temporary,
focusedWindowChangeAllowed,
time, cause);
// Motif compatibility code
case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive request - all events are generated.

View File

@@ -1258,7 +1258,7 @@ abstract class XDecoratedPeer extends XWindowPeer {
if (target == activeWindow && target != focusedWindow) {
// Happens when an owned window is currently focused
focusLog.fine("Focus is on child window - transferring it back to the owner");
handleWindowFocusInSync(-1, () -> {});
handleWindowFocusInSync(-1);
return true;
}
Window realNativeFocusedWindow = XWindowPeer.getNativeFocusedWindow();

View File

@@ -424,14 +424,13 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
return false;
}
static void sendEvent(final AWTEvent e, Runnable lightweigtRequestRunnable) {
static void sendEvent(final AWTEvent e) {
// The uses of this method imply that the incoming event is system-generated
SunToolkit.setSystemGenerated(e);
PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
public void run() {
AWTAccessor.getAWTEventAccessor().setPosted(e);
((Component)e.getSource()).dispatchEvent(e);
lightweigtRequestRunnable.run();
}
}, PeerEvent.ULTIMATE_PRIORITY_EVENT);
if (focusLog.isLoggable(PlatformLogger.Level.FINER) && (e instanceof FocusEvent)) {
@@ -440,9 +439,6 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
XToolkit.postEvent(XToolkit.targetToAppContext(e.getSource()), pe);
}
static void sendEvent(final AWTEvent e) {
sendEvent(e, () -> {});
}
/*
* Post an event to the event queue.

View File

@@ -618,15 +618,16 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
target.dispatchEvent(we);
}
}
public void handleWindowFocusInSync(long serial, Runnable lightweigtRequest) {
public void handleWindowFocusInSync(long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
sendEvent(we, lightweigtRequest);
sendEvent(we);
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleWindowFocusIn(long serial) {
handleWindowFocusInSync(serial, () -> {});
handleWindowFocusInSync(serial);
}
// NOTE: This method may be called by privileged threads.
@@ -847,16 +848,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("Requesting window focus");
}
Runnable finishRunnable = this::dequeueKeyEvents;
requestWindowFocus(time, timeProvided, finishRunnable, finishRunnable);
}
private void dequeueKeyEvents() {
AWTAccessor.getKeyboardFocusManagerAccessor().dequeueKeyEvents(target);
}
private void enqueueKeyEvents() {
AWTAccessor.getKeyboardFocusManagerAccessor().enqueueKeyEvents(target);
requestWindowFocus(time, timeProvided);
}
public final boolean focusAllowedFor() {
@@ -1144,17 +1136,14 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
warningWindow.setSecurityWarningVisible(false, false);
}
boolean refreshChildsTransientFor = isVisible() != vis;
// To enable type-ahead for 'simple' windows, we initiate internal focus transfer to such a window even before
// it's mapped by a window manager. 'Simple' windows aren't natively focusable, so for this to work as expected
// we only need to be sure that the window will be mapped soon after we request it. There are known cases when
// window manager delays mapping the window for a long time (e.g. i3wm does this when another window is in
// full-screen mode), but no known cases when it does it for popup windows, so we hope that we're safe here with
// 'simple' windows.
if (vis && isSimpleWindow() && shouldFocusOnMapNotify()) {
// We enable type-ahead mechanism only for showing of simple windows. That's because, when enabling it,
// we need to be sure that the final state (focusing) of the target window will definitely be available
// very soon, not to block key events for a long period of time. As simple windows are not focused natively,
// the only event we should wait for before focusing them internally is MapNotify, and that event usually
// comes quite fast after map request. There are known cases when window manager delays mapping the window
// for a long time (e.g. i3wm does this when another window is in full-screen mode), but no known cases
// when it does it for popup windows, so we hope that we're safe here with simple windows. For decorated
// windows we also wait for the native focus to be transferred to the target window (FocusIn event),
// which adds to the uncertainty - the focus might or might not be transferred.
enqueueKeyEvents();
requestInitialFocus();
}
super.setVisible(vis);
if (refreshChildsTransientFor) {
@@ -1223,7 +1212,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
if (targetOwner != null) {
XWindowPeer xwndpeer = AWTAccessor.getComponentAccessor().getPeer(targetOwner);
if (xwndpeer != null) {
xwndpeer.requestWindowFocus(() -> {}, () -> {});
xwndpeer.requestWindowFocus();
}
}
}
@@ -1495,15 +1484,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
}
}
if (shouldFocusOnMapNotify()) {
if (!isSimpleWindow() && shouldFocusOnMapNotify() && !XWM.isWeston()) {
focusLog.fine("Automatically request focus on window");
if (XWM.isWeston()) {
requestInitialFocusInternally();
} else {
requestInitialFocus();
}
} else {
dequeueKeyEvents();
requestInitialFocus();
}
isUnhiding = false;
isBeforeFirstMapNotify = false;
@@ -1555,18 +1538,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
requestXFocus();
}
// This will request focus without sending any requests to X server or window manager.
// It can only work for 'simple' windows, as their focusing is managed internally
// (natively, simple window's owner is seen as focused window).
private void requestInitialFocusInternally() {
if (isSimpleWindow() &&
XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner() == getDecoratedOwner((Window)target)) {
handleWindowFocusInSync(-1, this::dequeueKeyEvents);
} else {
dequeueKeyEvents();
}
}
public void addToplevelStateListener(ToplevelStateListener l){
toplevelStateListeners.add(l);
}
@@ -2067,25 +2038,16 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
return window;
}
public boolean requestWindowFocus(XWindowPeer actualFocusedWindow, Runnable lightweigtRequest, Runnable rejectFocusRequest) {
public boolean requestWindowFocus(XWindowPeer actualFocusedWindow) {
setActualFocusedWindow(actualFocusedWindow);
return requestWindowFocus(lightweigtRequest, rejectFocusRequest);
return requestWindowFocus();
}
public boolean requestWindowFocus() {
return requestWindowFocus(() -> {}, () -> {});
}
public boolean requestWindowFocus(Runnable lightweigtRequest, Runnable rejectFocusRequest) {
return requestWindowFocus(0, false, lightweigtRequest, rejectFocusRequest);
return requestWindowFocus(0, false);
}
public boolean requestWindowFocus(long time, boolean timeProvided) {
return requestWindowFocus(time, timeProvided, () -> {}, () -> {});
}
public boolean requestWindowFocus(long time, boolean timeProvided,
Runnable lightweigtRequest, Runnable rejectFocusRequest) {
focusLog.fine("Request for window focus");
// If this is Frame or Dialog we can't assure focus request success - but we still can try
// If this is Window and its owner Frame is active we can be sure request succedded.
@@ -2095,12 +2057,11 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
if (isWMStateNetHidden()) {
focusLog.fine("The window is unmapped, so rejecting the request");
rejectFocusRequest.run();
return false;
}
if (activeWindow == ownerWindow) {
focusLog.fine("Parent window is active - generating focus for this window");
handleWindowFocusInSync(-1, lightweigtRequest);
handleWindowFocusInSync(-1);
return true;
}
focusLog.fine("Parent window is not active");
@@ -2108,11 +2069,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
XDecoratedPeer wpeer = AWTAccessor.getComponentAccessor().getPeer(ownerWindow);
if (wpeer != null && wpeer.requestWindowFocus(this, time, timeProvided)) {
focusLog.fine("Parent window accepted focus request - generating focus for this window");
handleWindowFocusInSync(-1, lightweigtRequest);
return true;
}
focusLog.fine("Denied - parent window is not active and didn't accept focus request");
rejectFocusRequest.run();
return false;
}

View File

@@ -24,7 +24,8 @@ import java.awt.Window;
*/
public interface RoundedCornersManager {
/**
* @param params for macOS is Float object with radius.
* @param params for macOS is Float object with radius or
* Array with {Float for radius, Integer for border width, java.awt.Color for border color}.
*
* @param params for Windows 11 is String with values:
* "default" - let the system decide whether or not to round window corners,

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Dialog;
import java.awt.Frame;
import java.io.*;
import javax.swing.*;
import sun.awt.SunToolkit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @test
* @key headful
* @bug 8043705
* @summary Can't exit color chooser dialog when running as an applet
* @modules java.desktop/sun.awt
* @run main CloseDialogTest
*/
public class CloseDialogTest {
private static volatile Frame frame;
private static volatile Dialog dialog;
private static volatile InputStream testErrorStream;
private static final PrintStream systemErrStream = System.err;
private static final AtomicReference<Exception> caughtException
= new AtomicReference<>();
public static void main(String[] args) throws Exception {
// redirect System err
PipedOutputStream errorOutputStream = new PipedOutputStream();
testErrorStream = new PipedInputStream(errorOutputStream);
System.setErr(new PrintStream(errorOutputStream));
ThreadGroup swingTG = new ThreadGroup(getRootThreadGroup(), "SwingTG");
try {
new Thread(swingTG, () -> {
SunToolkit.createNewAppContext();
SwingUtilities.invokeLater(() -> {
frame = new Frame();
frame.setSize(300, 300);
frame.setVisible(true);
dialog = new Dialog(frame);
dialog.setSize(200, 200);
dialog.setModal(true);
dialog.setVisible(true);
});
}).start();
Thread.sleep(400);
Thread disposeThread = new Thread(swingTG, () ->
SwingUtilities.invokeLater(() -> {
try {
while (dialog == null || !dialog.isVisible()) {
Thread.sleep(100);
}
dialog.setVisible(false);
dialog.dispose();
frame.dispose();
} catch (Exception e) {
caughtException.set(e);
}
}));
disposeThread.start();
disposeThread.join();
Thread.sleep(500);
// read System err
final char[] buffer = new char[2048];
System.err.print("END");
System.setErr(systemErrStream);
try (Reader in = new InputStreamReader(testErrorStream, "UTF-8")) {
int size = in.read(buffer, 0, buffer.length);
String errorString = new String(buffer, 0, size);
if (!errorString.startsWith("END")) {
System.err.println(errorString.
substring(0, errorString.length() - 4));
throw new RuntimeException("Error output is not empty!");
}
}
} finally {
if (caughtException.get() != null) {
throw new RuntimeException("Failed. Caught exception!",
caughtException.get());
}
}
}
private static ThreadGroup getRootThreadGroup() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
while (threadGroup.getParent() != null) {
threadGroup = threadGroup.getParent();
}
return threadGroup;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2000-2021 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
@requires os.family == "mac" | os.family == "windows"
@key headful
@summary Test that window state changes on titlebar double-click
@library ../../../../java/awt/regtesthelpers
@build Util
@run shell build.sh
@run main CustomTitleBarDoubleClick
*/
import com.jetbrains.JBR;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class CustomTitleBarDoubleClick implements WindowListener, WindowStateListener {
//Declare things used in the test, like buttons and labels here
private final static Rectangle BOUNDS = new Rectangle(300, 300, 300, 300);
private final static int TITLE_BAR_OFFSET = 10;
JFrame frame;
Robot robot;
boolean stateChanged;
public static void main(final String[] args) {
CustomTitleBarDoubleClick app = new CustomTitleBarDoubleClick();
app.start();
}
public void start () {
robot = Util.createRobot();
robot.setAutoDelay(100);
robot.mouseMove(BOUNDS.x + (BOUNDS.width / 2),
BOUNDS.y + (BOUNDS.height/ 2));
frame = new JFrame("CustomTitleBarDoubleClick"); // Custom decorations doesn't work for AWT Frames on macOS
frame.setBounds(BOUNDS);
frame.addWindowListener(this);
frame.addWindowStateListener(this);
JBR.getCustomWindowDecoration().setCustomDecorationEnabled(frame, true);
JBR.getCustomWindowDecoration().setCustomDecorationTitleBarHeight(frame, 50);
frame.setVisible(true);
robot.delay(2000);
if (!stateChanged) throw new AWTError("Test failed");
}
// Move the mouse into the title bar and double click to maximize the Frame
static boolean hasRun = false;
private void doTest() {
if (hasRun) return;
hasRun = true;
System.out.println("doing test");
robot.mouseMove(BOUNDS.x + (BOUNDS.width / 2),
BOUNDS.y + TITLE_BAR_OFFSET);
robot.delay(50);
// Util.waitForIdle(robot) seem always hangs here.
// Need to use it instead robot.delay() when the bug become fixed.
System.out.println("1st press: currentTimeMillis: " + System.currentTimeMillis());
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.delay(50);
System.out.println("1st release: currentTimeMillis: " + System.currentTimeMillis());
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(50);
System.out.println("2nd press: currentTimeMillis: " + System.currentTimeMillis());
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.delay(50);
System.out.println("2nd release: currentTimeMillis: " + System.currentTimeMillis());
robot.mouseRelease(InputEvent.BUTTON1_MASK);
System.out.println("done: currentTimeMillis: " + System.currentTimeMillis());
}
public void windowActivated(WindowEvent e) {doTest();}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowStateChanged(WindowEvent e) {
stateChanged = true; // On macOS double-click may cause window to be maximized or iconified depending on AppleActionOnDoubleClick setting
}
}

View File

@@ -50,6 +50,8 @@ public class JBRApiTest {
private static void testServices() {
Objects.requireNonNull(JBR.getExtendedGlyphCache().getSubpixelResolution());
Objects.requireNonNull(JBRFileDialog.get(new FileDialog((Frame) null)));
Objects.requireNonNull(JBR.getRoundedCornersManager());
if (!System.getProperty("os.name").toLowerCase().contains("linux")) {
Objects.requireNonNull(JBR.getRoundedCornersManager());
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2022 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* @test
* @summary Regression test for JBR-4820 Focus lost after showing popup and context menu
* @key headful
*/
public class ContextMenuAfterPopup {
private static Robot robot;
private static JFrame frame;
private static JTextField frameField;
public static void main(String[] args) throws Exception {
robot = new Robot();
robot.setAutoDelay(50);
try {
SwingUtilities.invokeAndWait(ContextMenuAfterPopup::initUI);
robot.delay(1000);
clickOn(frameField);
robot.delay(1000);
type(KeyEvent.VK_ENTER);
robot.delay(1000);
type(KeyEvent.VK_SPACE);
robot.delay(1000);
type(KeyEvent.VK_ESCAPE);
robot.delay(1000);
type(KeyEvent.VK_A);
robot.delay(1000);
if (!"a".equals(frameField.getText())) {
throw new RuntimeException();
}
} finally {
SwingUtilities.invokeAndWait(ContextMenuAfterPopup::disposeUI);
}
}
private static void initUI() {
frame = new JFrame("ContextMenuAfterPopup");
frameField = new JTextField(30);
frameField.addActionListener(e -> {
JWindow popup = new JWindow(frame);
JButton b = new JButton("Show context menu");
b.addActionListener(ee -> {
popup.dispose();
JPopupMenu pm = new JPopupMenu();
pm.add("item 1");
pm.add("item 2");
pm.show(frameField, 20, 20);
});
popup.add(b);
popup.pack();
popup.setVisible(true);
});
frame.add(frameField);
frame.pack();
frame.setVisible(true);
}
private static void disposeUI() {
if (frame != null) frame.dispose();
}
private static void type(int keyCode) {
robot.keyPress(keyCode);
robot.keyRelease(keyCode);
}
private static void clickAt(int x, int y) {
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
private static void clickOn(Component component) {
Point location = component.getLocationOnScreen();
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
}
}

View File

@@ -406,7 +406,7 @@ java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFModeless3Test.java 825318
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal1Test.java 8253184 windows-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal2Test.java 8253184 windows-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal3Test.java 8253184 windows-all
java/awt/Modal/ModalInternalFrameTest/ModalInternalFrameTest.java 8253184 windows-all
java/awt/Modal/ModalInternalFrameTest/ModalInternalFrameTest.java 8253184,8159599 windows-all,linux-all #8253184 windows-all; 8159599 linux-all
java/awt/Modal/MultipleDialogs/MultipleDialogs1Test.java 8198665 macosx-all
java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java 8198665 macosx-all
java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all
@@ -918,12 +918,13 @@ javax/swing/JList/6462008/bug6462008.java
javax/swing/JMenu/6470128/bug6470128.java nobug windows-all
# no printer found
java/awt/print/PrinterJob/CheckPrivilege.java nobug generic-all
java/awt/print/PrinterJob/CheckPrivilege.java JBR-893 generic-all
java/awt/print/PrinterJob/ExceptionTest.java nobug generic-all
java/awt/print/PrinterJob/ExceptionFromPrintableIsIgnoredTest.java nobug generic-all
java/awt/print/PrinterJob/ImagePrinting/NullClipARGB.java nobug generic-all
java/awt/print/PrinterJob/LandscapeStackOverflow.java nobug generic-all
java/awt/print/PrinterJob/PaintText.java nobug generic-all
java/awt/print/PrinterJob/LandscapeStackOverflow.java JBR-893 generic-all
java/awt/print/PrinterJob/Margins.java JBR-893 generic-all
java/awt/print/PrinterJob/PaintText.java JBR-893 generic-all
java/awt/print/PrinterJob/PrintCrashTest.java nobug generic-all
java/awt/print/PrinterJob/PrtException.java nobug generic-all
javax/print/attribute/ChromaticityValues.java nobug generic-all