mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-29 04:39:43 +01:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dec27719cf | ||
|
|
c4fb2e5e55 | ||
|
|
9fdc75969b | ||
|
|
c2cdacaddd | ||
|
|
2e925883d5 | ||
|
|
a156c6b9bf | ||
|
|
75335543f2 | ||
|
|
c9143a3b22 | ||
|
|
8361529140 | ||
|
|
2988403307 | ||
|
|
43fdd6cd26 | ||
|
|
9e16583b83 | ||
|
|
390fc567ef | ||
|
|
3674766d65 | ||
|
|
3b0708af7d |
27
README.md
27
README.md
@@ -5,6 +5,16 @@
|
||||
JetBrains Runtime is a fork of [OpenJDK](https://github.com/openjdk/jdk) available for Windows, Mac OS X, and Linux.
|
||||
It includes a number enhancements in font rendering, HiDPI support, ligatures, performance improvements, and bugfixes.
|
||||
|
||||
## Releases
|
||||
Download the latest releases of JetBrains Runtime to use with JetBrains IDEs. The full list
|
||||
can be found on the [releases page](https://github.com/JetBrains/JetBrainsRuntime/releases).
|
||||
|
||||
| IDE Version | Latest JBR | Date Released |
|
||||
| --- | --- | --- |
|
||||
| 2021.2 | [11_0_11-b1504.13](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jb11_0_11-b1504.13) | 19-Jul-2021 |
|
||||
| 2021.1 | [11.0.11+9-b1341.60](https://confluence.jetbrains.com/pages/viewpage.action?pageId=218857477) | 15-Jun-2021 |
|
||||
| 2020.3 | [11_0_11-b1145.115](https://confluence.jetbrains.com/pages/viewpage.action?pageId=219349001) | 21-Jun-2021 |
|
||||
|
||||
## Contents
|
||||
- [Welcome to JetBrains Runtime](#jetbrains-runtime)
|
||||
- [Products Built on JetBrains Runtime](#products-built-on-jetbrains-runtime)
|
||||
@@ -75,7 +85,8 @@ $ docker run -v `pwd`../../../../:/JetBrainsRuntime -it 942ea9900054
|
||||
Install the necessary tools, libraries, and headers with:
|
||||
```
|
||||
$ sudo apt-get install autoconf make build-essential libx11-dev libxext-dev libxrender-dev libxtst-dev \
|
||||
libxt-dev libxrandr-dev libcups2-dev libfontconfig1-dev libasound2-dev
|
||||
libxt-dev libxrandr-dev libcups2-dev libfontconfig1-dev libasound2-dev \
|
||||
openjdk-11-jdk
|
||||
```
|
||||
Then run the following:
|
||||
```
|
||||
@@ -93,7 +104,7 @@ Install the following:
|
||||
* [Visual Studio compiler toolset](https://visualstudio.microsoft.com/downloads/).
|
||||
Install with the desktop development kit, which includes Windows SDK and compilers.
|
||||
Visual Studio 2015 is supported by default.
|
||||
* [Java 11](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
|
||||
* [Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html).
|
||||
If you have problems while configuring, read [Java tips on Cygwin](http://horstmann.com/articles/cygwin-tips.html).
|
||||
|
||||
From the command line:
|
||||
@@ -112,7 +123,9 @@ $ make images
|
||||
```
|
||||
|
||||
### macOS
|
||||
Install Xcode command line developer tools and `autoconf` via [Homebrew](getDpiInfo).
|
||||
Install the following:
|
||||
* Xcode command line developer tools and `autoconf` via [Homebrew](getDpiInfo).
|
||||
* [Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html).
|
||||
|
||||
From the command line:
|
||||
```
|
||||
@@ -126,7 +139,7 @@ We are happy to receive your pull requests!
|
||||
Before you submit one, please sign our [Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/).
|
||||
|
||||
## Resources
|
||||
* [JetBrains Runtime on github](https://github.com/JetBrains/JetBrainsRuntime)
|
||||
* [OpenJDK build instructions](http://hg.openjdk.java.net/jdk/jdk11/raw-file/tip/doc/building.html)
|
||||
* [OpenJDK test instructions](http://hg.openjdk.java.net/jdk/jdk11/raw-file/tip/doc/building.html#running-tests)
|
||||
* [How to develop OpenJDK with CLion](https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/)
|
||||
* [JetBrains Runtime on github](https://github.com/JetBrains/JetBrainsRuntime).
|
||||
* [OpenJDK build instructions](http://hg.openjdk.java.net/jdk/jdk11/raw-file/tip/doc/building.html).
|
||||
* [OpenJDK test instructions](http://hg.openjdk.java.net/jdk/jdk11/raw-file/tip/doc/building.html#running-tests).
|
||||
* [How to develop OpenJDK with CLion](https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/).
|
||||
|
||||
@@ -230,8 +230,8 @@ class LIR_OprDesc: public CompilationResourceObj {
|
||||
, is_xmm_bits = 1
|
||||
, last_use_bits = 1
|
||||
, is_fpu_stack_offset_bits = 1 // used in assertion checking on x86 for FPU stack slot allocation
|
||||
, non_data_bits = kind_bits + type_bits + size_bits + destroys_bits + last_use_bits +
|
||||
is_fpu_stack_offset_bits + virtual_bits + is_xmm_bits
|
||||
, non_data_bits = pointer_bits + kind_bits + type_bits + size_bits + destroys_bits + virtual_bits
|
||||
+ is_xmm_bits + last_use_bits + is_fpu_stack_offset_bits
|
||||
, data_bits = BitsPerInt - non_data_bits
|
||||
, reg_bits = data_bits / 2 // for two registers in one value encoding
|
||||
};
|
||||
@@ -648,6 +648,11 @@ class LIR_OprFact: public AllStatic {
|
||||
#endif // X86
|
||||
|
||||
static LIR_Opr virtual_register(int index, BasicType type) {
|
||||
if (index > LIR_OprDesc::vreg_max) {
|
||||
// Running out of virtual registers. Caller should bailout.
|
||||
return illegalOpr;
|
||||
}
|
||||
|
||||
LIR_Opr res;
|
||||
switch (type) {
|
||||
case T_OBJECT: // fall through
|
||||
|
||||
@@ -1047,20 +1047,21 @@ void LIRGenerator::move_to_phi(ValueStack* cur_state) {
|
||||
|
||||
|
||||
LIR_Opr LIRGenerator::new_register(BasicType type) {
|
||||
int vreg = _virtual_register_number;
|
||||
// add a little fudge factor for the bailout, since the bailout is
|
||||
// only checked periodically. This gives a few extra registers to
|
||||
// hand out before we really run out, which helps us keep from
|
||||
// tripping over assertions.
|
||||
if (vreg + 20 >= LIR_OprDesc::vreg_max) {
|
||||
bailout("out of virtual registers");
|
||||
if (vreg + 2 >= LIR_OprDesc::vreg_max) {
|
||||
// wrap it around
|
||||
int vreg_num = _virtual_register_number;
|
||||
// Add a little fudge factor for the bailout since the bailout is only checked periodically. This allows us to hand out
|
||||
// a few extra registers before we really run out which helps to avoid to trip over assertions.
|
||||
if (vreg_num + 20 >= LIR_OprDesc::vreg_max) {
|
||||
bailout("out of virtual registers in LIR generator");
|
||||
if (vreg_num + 2 >= LIR_OprDesc::vreg_max) {
|
||||
// Wrap it around and continue until bailout really happens to avoid hitting assertions.
|
||||
_virtual_register_number = LIR_OprDesc::vreg_base;
|
||||
vreg_num = LIR_OprDesc::vreg_base;
|
||||
}
|
||||
}
|
||||
_virtual_register_number += 1;
|
||||
return LIR_OprFact::virtual_register(vreg, type);
|
||||
LIR_Opr vreg = LIR_OprFact::virtual_register(vreg_num, type);
|
||||
assert(vreg != LIR_OprFact::illegal(), "ran out of virtual registers");
|
||||
return vreg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3884,8 +3884,8 @@ void MoveResolver::insert_move(Interval* from_interval, Interval* to_interval) {
|
||||
assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
|
||||
assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
|
||||
|
||||
LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
|
||||
LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
|
||||
LIR_Opr from_opr = get_virtual_register(from_interval);
|
||||
LIR_Opr to_opr = get_virtual_register(to_interval);
|
||||
|
||||
if (!_multiple_reads_allowed) {
|
||||
// the last_use flag is an optimization for FPU stack allocation. When the same
|
||||
@@ -3903,12 +3903,27 @@ void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
|
||||
assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
|
||||
assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
|
||||
|
||||
LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
|
||||
LIR_Opr to_opr = get_virtual_register(to_interval);
|
||||
_insertion_buffer.move(_insert_idx, from_opr, to_opr);
|
||||
|
||||
TRACE_LINEAR_SCAN(4, tty->print("MoveResolver: inserted move from constant "); from_opr->print(); tty->print_cr(" to %d (%d, %d)", to_interval->reg_num(), to_interval->assigned_reg(), to_interval->assigned_regHi()));
|
||||
}
|
||||
|
||||
LIR_Opr MoveResolver::get_virtual_register(Interval* interval) {
|
||||
// Add a little fudge factor for the bailout since the bailout is only checked periodically. This allows us to hand out
|
||||
// a few extra registers before we really run out which helps to avoid to trip over assertions.
|
||||
int reg_num = interval->reg_num();
|
||||
if (reg_num + 20 >= LIR_OprDesc::vreg_max) {
|
||||
_allocator->bailout("out of virtual registers in linear scan");
|
||||
if (reg_num + 2 >= LIR_OprDesc::vreg_max) {
|
||||
// Wrap it around and continue until bailout really happens to avoid hitting assertions.
|
||||
reg_num = LIR_OprDesc::vreg_base;
|
||||
}
|
||||
}
|
||||
LIR_Opr vreg = LIR_OprFact::virtual_register(reg_num, interval->type());
|
||||
assert(vreg != LIR_OprFact::illegal(), "ran out of virtual registers");
|
||||
return vreg;
|
||||
}
|
||||
|
||||
void MoveResolver::resolve_mappings() {
|
||||
TRACE_LINEAR_SCAN(4, tty->print_cr("MoveResolver: resolving mappings for Block B%d, index %d", _insert_list->block() != NULL ? _insert_list->block()->block_id() : -1, _insert_idx));
|
||||
|
||||
@@ -430,6 +430,7 @@ class MoveResolver: public StackObj {
|
||||
void append_insertion_buffer();
|
||||
void insert_move(Interval* from_interval, Interval* to_interval);
|
||||
void insert_move(LIR_Opr from_opr, Interval* to_interval);
|
||||
LIR_Opr get_virtual_register(Interval* interval);
|
||||
|
||||
DEBUG_ONLY(void verify_before_resolve();)
|
||||
void resolve_mappings();
|
||||
|
||||
@@ -1342,7 +1342,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
|
||||
public Point windowToLocal(Point p, LWWindowPeer wp) {
|
||||
LWComponentPeer<?, ?> cp = this;
|
||||
while (cp != wp) {
|
||||
while (cp != wp && cp != null) {
|
||||
Rectangle cpb = cp.getBounds();
|
||||
p.x -= cpb.x;
|
||||
p.y -= cpb.y;
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.awt.FontMetrics;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.Insets;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
@@ -42,9 +43,11 @@ import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
@@ -69,11 +72,8 @@ import sun.lwawt.LWToolkit;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
import sun.lwawt.LWWindowPeer.PeerType;
|
||||
import sun.lwawt.PlatformWindow;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import java.security.AccessController;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class CPlatformWindow extends CFRetainedResource implements PlatformWindow {
|
||||
|
||||
@@ -107,6 +107,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
private static native void nativeEnterFullScreenMode(long nsWindowPtr);
|
||||
private static native void nativeExitFullScreenMode(long nsWindowPtr);
|
||||
static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
|
||||
private static native boolean nativeDelayShowing(long nsWindowPtr);
|
||||
|
||||
// Loger to report issues happened during execution but that do not affect functionality
|
||||
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
|
||||
@@ -733,6 +734,16 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
private static LWWindowPeer getBlockerFor(Window window) {
|
||||
if (window != null) {
|
||||
ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(window);
|
||||
if (peer instanceof LWWindowPeer) {
|
||||
return ((LWWindowPeer)peer).getBlocker();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override // PlatformWindow
|
||||
public void setVisible(boolean visible) {
|
||||
// Configure stuff
|
||||
@@ -749,7 +760,17 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
// Actually show or hide the window
|
||||
LWWindowPeer blocker = (peer == null)? null : peer.getBlocker();
|
||||
if (blocker == null || !visible) {
|
||||
if (visible && delayShowing()) {
|
||||
if (blocker == null) {
|
||||
Window focusedWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
LWWindowPeer focusedWindowBlocker = getBlockerFor(focusedWindow);
|
||||
if (focusedWindowBlocker == peer) {
|
||||
// try to switch to target space if we're adding a modal dialog
|
||||
// that would block currently focused window
|
||||
owner.execute(CWrapper.NSWindow::orderFront);
|
||||
}
|
||||
}
|
||||
} else if (blocker == null || !visible) {
|
||||
// If it ain't blocked, or is being hidden, go regular way
|
||||
if (visible) {
|
||||
boolean isPopup = (target.getType() == Window.Type.POPUP);
|
||||
@@ -844,7 +865,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
// Manage parent-child relationship when showing
|
||||
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
|
||||
|
||||
if (visible) {
|
||||
if (visible && !delayShowing()) {
|
||||
// Order myself above my parent
|
||||
if (owner != null && owner.isVisible()) {
|
||||
owner.execute(ownerPtr -> {
|
||||
@@ -876,7 +897,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
// Deal with the blocker of the window being shown
|
||||
if (blocker != null && visible) {
|
||||
// Make sure the blocker is above its siblings
|
||||
((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings();
|
||||
CPlatformWindow blockerWindow = (CPlatformWindow) blocker.getPlatformWindow();
|
||||
if (!blockerWindow.delayShowing()) {
|
||||
blockerWindow.orderAboveSiblings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,6 +935,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
@Override // PlatformWindow
|
||||
public void toFront() {
|
||||
if (delayShowing()) return;
|
||||
LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit();
|
||||
Window w = DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
||||
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
|
||||
@@ -965,6 +990,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
@Override
|
||||
public boolean requestWindowFocus() {
|
||||
if (delayShowing()) return false;
|
||||
execute(ptr -> {
|
||||
if (CWrapper.NSWindow.canBecomeMainWindow(ptr)) {
|
||||
CWrapper.NSWindow.makeMainWindow(ptr);
|
||||
@@ -983,6 +1009,17 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return ref.get();
|
||||
}
|
||||
|
||||
// We want a window to be always shown at the same space as its owning window.
|
||||
// But macOS doesn't have an API to control the target space for a window -
|
||||
// it's always shown at the active space. So if the target space isn't active now,
|
||||
// the only way to achieve our goal seems to be delaying the appearance of the
|
||||
// window till the target space becomes active.
|
||||
private boolean delayShowing() {
|
||||
AtomicBoolean ref = new AtomicBoolean(false);
|
||||
execute(ptr -> ref.set(nativeDelayShowing(ptr)));
|
||||
return ref.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFocusableWindowState() {
|
||||
setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, getFocusableStyleBits()); // set both bits at once
|
||||
@@ -1101,7 +1138,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
}
|
||||
nativeSetEnabled(ptr, !blocked);
|
||||
});
|
||||
checkBlockingAndOrder();
|
||||
}
|
||||
|
||||
public final void invalidateShadow() {
|
||||
@@ -1279,29 +1315,32 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
isFocusable ? focusableStyleBits : 0); // set both bits at once
|
||||
}
|
||||
|
||||
private boolean checkBlockingAndOrder() {
|
||||
private void checkBlockingAndOrder() {
|
||||
LWWindowPeer blocker = (peer == null)? null : peer.getBlocker();
|
||||
if (blocker == null) {
|
||||
return false;
|
||||
// If it's not blocked, make sure it's above its siblings
|
||||
orderAboveSiblings();
|
||||
return;
|
||||
}
|
||||
|
||||
if (blocker instanceof CPrinterDialogPeer) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
CPlatformWindow pWindow = (CPlatformWindow)blocker.getPlatformWindow();
|
||||
|
||||
pWindow.orderAboveSiblings();
|
||||
if (!pWindow.delayShowing()) {
|
||||
pWindow.orderAboveSiblings();
|
||||
|
||||
pWindow.execute(ptr -> {
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("Focus blocker " + Long.toHexString(ptr));
|
||||
}
|
||||
CWrapper.NSWindow.orderFrontRegardless(ptr);
|
||||
CWrapper.NSWindow.makeKeyAndOrderFront(ptr);
|
||||
CWrapper.NSWindow.makeMainWindow(ptr);
|
||||
});
|
||||
return true;
|
||||
pWindow.execute(ptr -> {
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("Focus blocker " + Long.toHexString(ptr));
|
||||
}
|
||||
CWrapper.NSWindow.orderFrontRegardless(ptr);
|
||||
CWrapper.NSWindow.makeKeyAndOrderFront(ptr);
|
||||
CWrapper.NSWindow.makeMainWindow(ptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isIconified() {
|
||||
@@ -1363,7 +1402,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
if (p instanceof LWWindowPeer) {
|
||||
CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
|
||||
iconified = isIconified();
|
||||
if (pw != null && pw.isVisible() && !iconified) {
|
||||
if (pw != null && pw.isVisible() && !iconified && !pw.delayShowing()) {
|
||||
// If the window is one of ancestors of 'main window' or is going to become main by itself,
|
||||
// the window should be ordered above its siblings; otherwise the window is just ordered
|
||||
// above its nearest parent.
|
||||
@@ -1435,9 +1474,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
private void windowDidBecomeMain() {
|
||||
lastBecomeMainTime = System.currentTimeMillis();
|
||||
if (checkBlockingAndOrder()) return;
|
||||
// If it's not blocked, make sure it's above its siblings
|
||||
orderAboveSiblings();
|
||||
checkBlockingAndOrder();
|
||||
}
|
||||
|
||||
private void windowWillEnterFullScreen() {
|
||||
|
||||
@@ -867,7 +867,7 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, N
|
||||
|
||||
- (void)setAccessibilitySelectedText:(NSString *)accessibilitySelectedText {
|
||||
id focused = [self accessibilityFocusedUIElement];
|
||||
if ([focused respondsToSelector:@selector(setAccessibilitySelectedText)]) {
|
||||
if ([focused respondsToSelector:@selector(setAccessibilitySelectedText:)]) {
|
||||
[focused setAccessibilitySelectedText:accessibilitySelectedText];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,9 +376,10 @@ AWT_NS_WINDOW_IMPLEMENTATION
|
||||
|
||||
if (IS(mask, FULLSCREENABLE) && [self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
|
||||
if (IS(bits, FULLSCREENABLE)) {
|
||||
[self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
|
||||
[self.nsWindow setCollectionBehavior:
|
||||
NSWindowCollectionBehaviorFullScreenPrimary | NSWindowCollectionBehaviorManaged];
|
||||
} else {
|
||||
[self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];
|
||||
[self.nsWindow setCollectionBehavior: NSWindowCollectionBehaviorManaged];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,10 +442,6 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
self.ownerWindow = owner;
|
||||
[self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
|
||||
|
||||
if (IS(self.styleBits, IS_POPUP)) {
|
||||
[self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/];
|
||||
}
|
||||
|
||||
self.javaWindowTabbingMode = [self getJavaWindowTabbingMode];
|
||||
self.isEnterFullScreen = NO;
|
||||
self.isJustCreated = YES;
|
||||
@@ -601,6 +598,43 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
- (BOOL) delayShowing {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
return ownerWindow != nil && ([ownerWindow delayShowing] || !ownerWindow.nsWindow.onActiveSpace)
|
||||
&& !nsWindow.visible;
|
||||
}
|
||||
|
||||
- (void) checkBlockingAndOrder {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
|
||||
if (platformWindow != NULL) {
|
||||
static JNF_MEMBER_CACHE(jm_checkBlockingAndOrder, jc_CPlatformWindow,
|
||||
"checkBlockingAndOrder", "()V");
|
||||
JNFCallVoidMethod(env, platformWindow, jm_checkBlockingAndOrder);
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)activeSpaceDidChange {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
for (NSWindow* window in [NSApp windows]) {
|
||||
if (window.onActiveSpace && [AWTWindow isJavaPlatformWindowVisible:window]) {
|
||||
AWTWindow *awtWindow = (AWTWindow *)[window delegate];
|
||||
// there can be only one current blocker per window hierarchy,
|
||||
// so we're checking just hierarchy root
|
||||
if (awtWindow.ownerWindow == nil) {
|
||||
// this should ensure that delayed blocking windows
|
||||
// show up on space activation
|
||||
[awtWindow checkBlockingAndOrder];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Orders window's childs based on the current focus state
|
||||
- (void) orderChildWindows:(BOOL)focus {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
@@ -632,9 +666,11 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
// back to normal window level
|
||||
[window setLevel:NSNormalWindowLevel];
|
||||
}
|
||||
// The childWindow should be displayed in front of
|
||||
// its nearest parentWindow
|
||||
[window orderWindow:NSWindowAbove relativeTo:[owner.nsWindow windowNumber]];
|
||||
if (window.onActiveSpace && owner.nsWindow.onActiveSpace) {
|
||||
// The childWindow should be displayed in front of
|
||||
// its nearest parentWindow
|
||||
[window orderWindow:NSWindowAbove relativeTo:[owner.nsWindow windowNumber]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
awtWindow = awtWindow.ownerWindow;
|
||||
@@ -668,14 +704,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
// We should bring up the modal dialog manually
|
||||
[AWTToolkit eventCountPlusPlus];
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
|
||||
if (platformWindow != NULL) {
|
||||
static JNF_MEMBER_CACHE(jm_checkBlockingAndOrder, jc_CPlatformWindow,
|
||||
"checkBlockingAndOrder", "()Z");
|
||||
JNFCallBooleanMethod(env, platformWindow, jm_checkBlockingAndOrder);
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
}
|
||||
[self checkBlockingAndOrder];
|
||||
}
|
||||
|
||||
return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
|
||||
@@ -1805,3 +1834,25 @@ JNF_COCOA_ENTER(env);
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CPlatformWindow
|
||||
* Method: nativeDelayShowing
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeDelayShowing
|
||||
(JNIEnv *env, jclass clazz, jlong windowPtr)
|
||||
{
|
||||
__block jboolean result = JNI_FALSE;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
NSWindow *nsWindow = (NSWindow *)jlong_to_ptr(windowPtr);
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
|
||||
result = [window delayShowing];
|
||||
}];
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#import "CMenuBar.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import "NSApplicationAWT.h"
|
||||
|
||||
#import "AWTWindow.h"
|
||||
|
||||
#pragma mark App Menu helpers
|
||||
|
||||
@@ -258,6 +258,11 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[ctr addObserver:clz selector:@selector(_appDidHide) name:NSApplicationDidHideNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(_appDidUnhide) name:NSApplicationDidUnhideNotification object:nil];
|
||||
|
||||
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:[AWTWindow class]
|
||||
selector:@selector(activeSpaceDidChange)
|
||||
name:NSWorkspaceActiveSpaceDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
if (children == NULL) {
|
||||
NSString *javaRole = [self javaRole];
|
||||
JavaComponentAccessibility *newChild = [JavaComponentAccessibility createWithParent:self
|
||||
accessible:self->fAccessible
|
||||
role:javaRole
|
||||
index:self->fIndex
|
||||
withEnv:[ThreadUtilities getJNIEnv]
|
||||
withView:self->fView
|
||||
isWrapped:YES];
|
||||
accessible:self->fAccessible
|
||||
role:javaRole
|
||||
index:self->fIndex
|
||||
withEnv:[ThreadUtilities getJNIEnv]
|
||||
withView:self->fView
|
||||
isWrapped:NO];
|
||||
return [NSArray arrayWithObject:newChild];
|
||||
} else {
|
||||
return children;
|
||||
|
||||
@@ -33,8 +33,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getC
|
||||
NSUInteger childIndex = [self columnNumberInTable];
|
||||
|
||||
int inc = [(JavaTableAccessibility *)[self accessibilityParent] accessibleColCount] * 2;
|
||||
NSInteger i = childIndex * 2;
|
||||
for(NSInteger i; i < arrayLen; i += inc)
|
||||
for(NSInteger i = childIndex * 2; i < arrayLen; i += inc)
|
||||
{
|
||||
jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i);
|
||||
jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1);
|
||||
@@ -52,7 +51,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getC
|
||||
withIndex:childIndex
|
||||
withView:self->fView
|
||||
withJavaRole:childJavaRole];
|
||||
[childrenCells addObject:[child autorelease]];
|
||||
[childrenCells addObject:[[child retain] autorelease]];
|
||||
|
||||
(*env)->DeleteLocalRef(env, jchild);
|
||||
(*env)->DeleteLocalRef(env, jchildJavaRole);
|
||||
|
||||
@@ -545,11 +545,6 @@ static void RaiseMustOverrideException(NSString *method)
|
||||
return size;
|
||||
}
|
||||
|
||||
- (id)getFocusedElement
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (jobject)accessible {
|
||||
return fAccessible;
|
||||
}
|
||||
@@ -590,13 +585,13 @@ static void RaiseMustOverrideException(NSString *method)
|
||||
if (axAction != NULL) {
|
||||
JNF_CLASS_CACHE(jc_AccessibleAction, "javax/accessibility/AccessibleAction");
|
||||
JNF_MEMBER_CACHE(jm_getAccessibleActionCount, jc_AccessibleAction, "getAccessibleActionCount", "()I");
|
||||
jint count = JNFCallObjectMethod(env, axAction, jm_getAccessibleActionCount);
|
||||
jint count = JNFCallIntMethod(env, axAction, jm_getAccessibleActionCount);
|
||||
fActions = [[NSMutableDictionary alloc] initWithCapacity:count];
|
||||
fActionSElectors = [[NSMutableArray alloc] initWithCapacity:count];
|
||||
for (int i =0; i < count; i++) {
|
||||
JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:i withComponent:fComponent];
|
||||
if ([fParent isKindOfClass:[JavaComponentAccessibility class]] &&
|
||||
[fParent isMenu] &&
|
||||
[(JavaComponentAccessibility *)fParent isMenu] &&
|
||||
[[sActions objectForKey:[action getDescription]] isEqualToString:NSAccessibilityPressAction]) {
|
||||
[fActions setObject:action forKey:NSAccessibilityPickAction];
|
||||
[fActionSElectors addObject:[sActionSelectores objectForKey:NSAccessibilityPickAction]];
|
||||
@@ -878,16 +873,16 @@ static void RaiseMustOverrideException(NSString *method)
|
||||
// cmcnote - should batch these two calls into one that returns an array of two bools, one for vertical and one for horiz
|
||||
if (isVertical(env, axContext, fComponent)) {
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return NSAccessibilityVerticalOrientationValue;
|
||||
return NSAccessibilityOrientationVertical;
|
||||
}
|
||||
|
||||
if (isHorizontal(env, axContext, fComponent)) {
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return NSAccessibilityHorizontalOrientationValue;
|
||||
return NSAccessibilityOrientationHorizontal;
|
||||
}
|
||||
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return nil;
|
||||
return NSAccessibilityOrientationUnknown;
|
||||
}
|
||||
|
||||
- (NSPoint)accessibilityActivationPoint
|
||||
|
||||
@@ -20,14 +20,16 @@ static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getC
|
||||
- (NSArray *)accessibilityChildren {
|
||||
NSArray *children = [super accessibilityChildren];
|
||||
if (children == NULL) {
|
||||
|
||||
// Since the row element has already been created, we should no create it again, but just retrieve it by a pointer, that's why isWrapped is set to YES.
|
||||
JavaComponentAccessibility *newChild = [JavaComponentAccessibility createWithParent:self
|
||||
accessible:self->fAccessible
|
||||
role:self->fJavaRole
|
||||
index:self->fIndex
|
||||
withEnv:[ThreadUtilities getJNIEnv]
|
||||
withView:self->fView
|
||||
isWrapped:YES];
|
||||
return [NSArray arrayWithObject:[newChild autorelease]];
|
||||
accessible:self->fAccessible
|
||||
role:self->fJavaRole
|
||||
index:self->fIndex
|
||||
withEnv:[ThreadUtilities getJNIEnv]
|
||||
withView:self->fView
|
||||
isWrapped:YES];
|
||||
return [NSArray arrayWithObject:newChild];
|
||||
} else {
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAc
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I");
|
||||
jint row = JNFCallStaticIntMethod(env, jm_getLineNumberForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if (row < 0) return nil;
|
||||
if (row < 0) return 0;
|
||||
return row;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAc
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText, "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I");
|
||||
jint row = JNFCallStaticIntMethod(env, jm_getLineNumberForInsertionPoint, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if (row < 0) return nil;
|
||||
if (row < 0) return 0;
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,10 @@ static BOOL javaObjectEquals(JNIEnv *env, jobject a, jobject b, jobject componen
|
||||
// NSAccessibilityElement protocol methods
|
||||
|
||||
- (NSAccessibilitySubrole)accessibilitySubrole {
|
||||
return NSAccessibilityTabButtonSubrole;
|
||||
if (@available(macOS 10.13, *)) {
|
||||
return NSAccessibilityTabButtonSubrole;
|
||||
}
|
||||
return NSAccessibilityUnknownSubrole;
|
||||
}
|
||||
|
||||
- (id)accessibilityValue {
|
||||
|
||||
@@ -35,9 +35,8 @@ static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getC
|
||||
NSMutableArray *childrenCells = [NSMutableArray arrayWithCapacity:arrayLen/2];
|
||||
|
||||
NSUInteger childIndex = [self rowNumberInTable] * [(JavaTableAccessibility *)parent accessibleColCount];
|
||||
NSInteger i = childIndex * 2;
|
||||
NSInteger n = ([self rowNumberInTable] + 1) * [(JavaTableAccessibility *)parent accessibleColCount] * 2;
|
||||
for(i; i < n; i+=2)
|
||||
for (NSInteger i = childIndex * 2; i < n; i+=2)
|
||||
{
|
||||
jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i);
|
||||
jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1);
|
||||
@@ -55,7 +54,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getC
|
||||
withIndex:childIndex
|
||||
withView:self->fView
|
||||
withJavaRole:childJavaRole];
|
||||
[childrenCells addObject:[child autorelease]];
|
||||
[childrenCells addObject:[[child retain] autorelease]];
|
||||
|
||||
(*env)->DeleteLocalRef(env, jchild);
|
||||
(*env)->DeleteLocalRef(env, jchildJavaRole);
|
||||
@@ -70,7 +69,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getC
|
||||
}
|
||||
|
||||
- (NSInteger)accessibilityIndex {
|
||||
return [[self accessibilityParent] accessibilityIndexOfChild:self];
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityLabel {
|
||||
|
||||
@@ -870,7 +870,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
|
||||
* @see Component#dispatchEvent
|
||||
*/
|
||||
public boolean dispatchKeyEvent(KeyEvent e) {
|
||||
Component focusOwner = (((AWTEvent)e).isPosted && e.getID() != KeyEvent.KEY_TYPED) ? getFocusOwner() : e.getComponent();
|
||||
Component focusOwner = (((AWTEvent)e).isPosted &&
|
||||
!(e.getID() == KeyEvent.KEY_TYPED && SunToolkit.isSystemGenerated(e)))
|
||||
? getFocusOwner() : e.getComponent();
|
||||
|
||||
if (focusOwner != null && focusOwner.isShowing() && focusOwner.canBeFocusOwner()) {
|
||||
if (!e.isConsumed()) {
|
||||
@@ -1098,14 +1100,18 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
|
||||
private boolean preDispatchKeyEvent(KeyEvent ke) {
|
||||
getOnTypeaheadFinishedHandler().accept(ke);
|
||||
if (((AWTEvent) ke).isPosted) {
|
||||
boolean typedEvent = ke.getID() == KeyEvent.KEY_TYPED;
|
||||
boolean systemEvent = SunToolkit.isSystemGenerated(ke);
|
||||
Component focusOwner;
|
||||
if (ke.getID() == KeyEvent.KEY_TYPED) {
|
||||
if (typedEvent && systemEvent) {
|
||||
focusOwner = lastKeyPressedOrReleasedTarget.get();
|
||||
} else {
|
||||
focusOwner = getFocusOwner();
|
||||
if (focusOwner == null) {
|
||||
focusOwner = getFocusedWindow();
|
||||
}
|
||||
}
|
||||
if (!typedEvent && systemEvent) {
|
||||
lastKeyPressedOrReleasedTarget = new WeakReference<>(focusOwner);
|
||||
}
|
||||
ke.setSource(focusOwner);
|
||||
|
||||
@@ -663,6 +663,13 @@ public class Dialog extends Window {
|
||||
public Dialog(Window owner, String title, ModalityType modalityType) {
|
||||
super(owner);
|
||||
|
||||
if ((owner != null) &&
|
||||
!(owner instanceof Frame) &&
|
||||
!(owner instanceof Dialog))
|
||||
{
|
||||
throw new IllegalArgumentException("Wrong parent window");
|
||||
}
|
||||
|
||||
this.title = title;
|
||||
setModalityType(modalityType);
|
||||
SunToolkit.checkAndSetPolicy(this);
|
||||
|
||||
@@ -1071,7 +1071,13 @@ public class Window extends Container implements Accessible {
|
||||
} else {
|
||||
// fix for 6532736: after this window is shown, its blocker
|
||||
// should be raised to front
|
||||
modalBlocker.toFront_NoClientCode();
|
||||
boolean storedValue = modalBlocker.isAutoRequestFocus();
|
||||
modalBlocker.setAutoRequestFocus(false);
|
||||
try {
|
||||
modalBlocker.toFront_NoClientCode();
|
||||
} finally {
|
||||
modalBlocker.setAutoRequestFocus(storedValue);
|
||||
}
|
||||
}
|
||||
if (this instanceof Frame || this instanceof Dialog) {
|
||||
updateChildFocusableWindowState(this);
|
||||
|
||||
4068
test/hotspot/jtreg/compiler/c1/TestTooManyVirtualRegisters.jasm
Normal file
4068
test/hotspot/jtreg/compiler/c1/TestTooManyVirtualRegisters.jasm
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8261235
|
||||
* @requires vm.compiler1.enabled
|
||||
* @summary Tests custom bytecode which requires too many virtual registers in the linear scan of C1.
|
||||
* The test should bail out in C1.
|
||||
*
|
||||
* @compile TestTooManyVirtualRegisters.jasm
|
||||
* @run main/othervm -Xbatch -XX:CompileCommand=dontinline,compiler.c1.TestExceptionBlockWithPredecessors::*
|
||||
* compiler.c1.TestTooManyVirtualRegistersMain
|
||||
*/
|
||||
|
||||
package compiler.c1;
|
||||
|
||||
public class TestTooManyVirtualRegistersMain {
|
||||
public static void main(String[] args) {
|
||||
for (char i = 0; i < 10000; i++) {
|
||||
TestTooManyVirtualRegisters.test(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
129
test/jdk/jb/java/awt/Window/FullScreenChildWindow.java
Normal file
129
test/jdk/jb/java/awt/Window/FullScreenChildWindow.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2021 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 com.apple.eawt.Application;
|
||||
import com.apple.eawt.FullScreenAdapter;
|
||||
import com.apple.eawt.FullScreenUtilities;
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-3611 Unexpected workspace switch with dialog in full-screen mode on macOS
|
||||
* @key headful
|
||||
* @requires (os.family == "mac")
|
||||
* @modules java.desktop/com.apple.eawt
|
||||
* java.desktop/com.apple.eawt.event
|
||||
*/
|
||||
|
||||
public class FullScreenChildWindow {
|
||||
private static final CompletableFuture<Boolean> shownAtFullScreen = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> dialogShown = new CompletableFuture<>();
|
||||
|
||||
private static Robot robot;
|
||||
private static JFrame frame2;
|
||||
private static JFrame frame1;
|
||||
private static JButton button;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(FullScreenChildWindow::initUI);
|
||||
shownAtFullScreen.get(5, TimeUnit.SECONDS);
|
||||
clickAt(button);
|
||||
dialogShown.get(5, TimeUnit.SECONDS);
|
||||
switchToPreviousSpace();
|
||||
robot.delay(2000);
|
||||
if (!frame1.isFocused()) {
|
||||
throw new RuntimeException("Unexpected state");
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(FullScreenChildWindow::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame1 = new JFrame("FullScreenChildWindow(1)");
|
||||
frame1.setSize(100, 100);
|
||||
frame1.setLocation(100, 100);
|
||||
frame1.setVisible(true);
|
||||
|
||||
frame2 = new JFrame("FullScreenChildWindow(2)");
|
||||
button = new JButton("Open dialog");
|
||||
button.addActionListener(e -> {
|
||||
JDialog d = new JDialog(frame2, "dialog", false);
|
||||
d.setSize(100, 100);
|
||||
d.setLocationRelativeTo(null);
|
||||
d.setAutoRequestFocus(false);
|
||||
d.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
dialogShown.complete(true);
|
||||
}
|
||||
});
|
||||
d.setVisible(true);
|
||||
});
|
||||
frame2.add(button);
|
||||
frame2.setSize(100, 100);
|
||||
frame2.setLocation(100, 300);
|
||||
frame2.setVisible(true);
|
||||
FullScreenUtilities.addFullScreenListenerTo(frame2, new FullScreenAdapter() {
|
||||
@Override
|
||||
public void windowEnteredFullScreen(FullScreenEvent e) {
|
||||
shownAtFullScreen.complete(true);
|
||||
}
|
||||
});
|
||||
Application.getApplication().requestToggleFullScreen(frame2);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame2 != null) frame2.dispose();
|
||||
if (frame1 != null) frame1.dispose();
|
||||
}
|
||||
|
||||
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 clickAt(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
|
||||
private static void switchToPreviousSpace() {
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(KeyEvent.VK_LEFT);
|
||||
robot.keyRelease(KeyEvent.VK_LEFT);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
}
|
||||
}
|
||||
145
test/jdk/jb/java/awt/Window/FullScreenInactiveDialog.java
Normal file
145
test/jdk/jb/java/awt/Window/FullScreenInactiveDialog.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2021 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 com.apple.eawt.Application;
|
||||
import com.apple.eawt.FullScreenAdapter;
|
||||
import com.apple.eawt.FullScreenUtilities;
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-3633 Modal dialog is shown not at the same space as its parent
|
||||
* @key headful
|
||||
* @requires (os.family == "mac")
|
||||
* @modules java.desktop/com.apple.eawt
|
||||
* java.desktop/com.apple.eawt.event
|
||||
*/
|
||||
|
||||
public class FullScreenInactiveDialog {
|
||||
private static final CompletableFuture<Boolean> shownAtFullScreen = new CompletableFuture<>();
|
||||
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JDialog dialog;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(FullScreenInactiveDialog::initUI);
|
||||
shownAtFullScreen.get(5, TimeUnit.SECONDS);
|
||||
switchToPreviousSpace();
|
||||
SwingUtilities.invokeLater(FullScreenInactiveDialog::openDialog);
|
||||
robot.delay(1000);
|
||||
if (isWindowReallyShowing(dialog)) {
|
||||
throw new RuntimeException("Dialog is showing earlier than expected");
|
||||
}
|
||||
activateApp(); // simulates clicking on app icon in dock or switch using Cmd+Tab
|
||||
if (!isWindowReallyShowing(dialog)) {
|
||||
throw new RuntimeException("Dialog isn't showing when expected");
|
||||
}
|
||||
if (!isWindowReallyShowing(frame)) {
|
||||
throw new RuntimeException("Frame isn't showing when expected");
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(FullScreenInactiveDialog::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("FullScreenInactiveDialog");
|
||||
frame.setSize(300, 100);
|
||||
frame.setVisible(true);
|
||||
|
||||
|
||||
FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenAdapter() {
|
||||
@Override
|
||||
public void windowEnteredFullScreen(FullScreenEvent e) {
|
||||
shownAtFullScreen.complete(true);
|
||||
}
|
||||
});
|
||||
Application.getApplication().requestToggleFullScreen(frame);
|
||||
}
|
||||
|
||||
private static void openDialog() {
|
||||
dialog = new JDialog(frame);
|
||||
dialog.setSize(100, 100);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void switchToPreviousSpace() {
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(KeyEvent.VK_LEFT);
|
||||
robot.keyRelease(KeyEvent.VK_LEFT);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
robot.delay(1000); // wait for animation to finish
|
||||
}
|
||||
|
||||
private static void activateApp() {
|
||||
Desktop.getDesktop().requestForeground(false);
|
||||
robot.delay(1000); // wait for animation to finish
|
||||
}
|
||||
|
||||
private static boolean isWindowReallyShowing(Window window) throws Exception {
|
||||
Point[] location = new Point[1];
|
||||
AtomicBoolean movementDetected = new AtomicBoolean();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
if (window.isVisible()) {
|
||||
Rectangle bounds = window.getBounds();
|
||||
Insets insets = window.getInsets();
|
||||
bounds.x += insets.left;
|
||||
bounds.y += insets.top;
|
||||
bounds.width -= insets.left + insets.right;
|
||||
bounds.height -= insets.top + insets.bottom;
|
||||
if (!bounds.isEmpty()) {
|
||||
location[0] = new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
|
||||
window.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
movementDetected.set(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Point target = location[0];
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
robot.mouseMove(target.x, target.y);
|
||||
robot.delay(100);
|
||||
robot.mouseMove(target.x + 1, target.y + 1);
|
||||
robot.delay(1000);
|
||||
return movementDetected.get();
|
||||
}
|
||||
}
|
||||
145
test/jdk/jb/java/awt/Window/FullScreenInactiveModalDialog.java
Normal file
145
test/jdk/jb/java/awt/Window/FullScreenInactiveModalDialog.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2000-2021 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 com.apple.eawt.Application;
|
||||
import com.apple.eawt.FullScreenAdapter;
|
||||
import com.apple.eawt.FullScreenUtilities;
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-3633 Modal dialog is shown not at the same space as its parent
|
||||
* @key headful
|
||||
* @requires (os.family == "mac")
|
||||
* @modules java.desktop/com.apple.eawt
|
||||
* java.desktop/com.apple.eawt.event
|
||||
*/
|
||||
|
||||
public class FullScreenInactiveModalDialog {
|
||||
private static final CompletableFuture<Boolean> shownAtFullScreen = new CompletableFuture<>();
|
||||
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JDialog dialog;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(FullScreenInactiveModalDialog::initUI);
|
||||
shownAtFullScreen.get(5, TimeUnit.SECONDS);
|
||||
switchToPreviousSpace();
|
||||
SwingUtilities.invokeLater(FullScreenInactiveModalDialog::openDialog);
|
||||
robot.delay(1000);
|
||||
if (isWindowReallyShowing(dialog)) {
|
||||
throw new RuntimeException("Dialog is showing earlier than expected");
|
||||
}
|
||||
switchToNextSpace();
|
||||
if (!isWindowReallyShowing(dialog)) {
|
||||
throw new RuntimeException("Dialog isn't showing when expected");
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(FullScreenInactiveModalDialog::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("FullScreenInactiveModalDialog");
|
||||
frame.setSize(300, 100);
|
||||
frame.setVisible(true);
|
||||
|
||||
|
||||
FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenAdapter() {
|
||||
@Override
|
||||
public void windowEnteredFullScreen(FullScreenEvent e) {
|
||||
shownAtFullScreen.complete(true);
|
||||
}
|
||||
});
|
||||
Application.getApplication().requestToggleFullScreen(frame);
|
||||
}
|
||||
|
||||
private static void openDialog() {
|
||||
dialog = new JDialog(frame, true);
|
||||
dialog.setSize(100, 100);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void switchToPreviousSpace() {
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(KeyEvent.VK_LEFT);
|
||||
robot.keyRelease(KeyEvent.VK_LEFT);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
robot.delay(1000); // wait for animation to finish
|
||||
}
|
||||
|
||||
private static void switchToNextSpace() {
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(KeyEvent.VK_RIGHT);
|
||||
robot.keyRelease(KeyEvent.VK_RIGHT);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
robot.delay(1000); // wait for animation to finish
|
||||
}
|
||||
|
||||
private static boolean isWindowReallyShowing(Window window) throws Exception {
|
||||
Point[] location = new Point[1];
|
||||
AtomicBoolean movementDetected = new AtomicBoolean();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
if (window.isVisible()) {
|
||||
Rectangle bounds = window.getBounds();
|
||||
Insets insets = window.getInsets();
|
||||
bounds.x += insets.left;
|
||||
bounds.y += insets.top;
|
||||
bounds.width -= insets.left + insets.right;
|
||||
bounds.height -= insets.top + insets.bottom;
|
||||
if (!bounds.isEmpty()) {
|
||||
location[0] = new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
|
||||
window.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
movementDetected.set(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Point target = location[0];
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
robot.mouseMove(target.x, target.y);
|
||||
robot.delay(100);
|
||||
robot.mouseMove(target.x + 1, target.y + 1);
|
||||
robot.delay(1000);
|
||||
return movementDetected.get();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user