mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-10 15:08:43 +00:00
8381037: Remove AppContext from miscellaneous awt shared classes
Reviewed-by: azvegint, dnguyen
This commit is contained in:
parent
9131c72d63
commit
3cb4d7db19
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2026, 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
|
||||
@ -203,8 +203,8 @@ class EventDispatchThread extends Thread {
|
||||
eq.dispatchEvent(event);
|
||||
}
|
||||
catch (InterruptedException interruptedException) {
|
||||
doDispatch = false; // AppContext.dispose() interrupts all
|
||||
// Threads in the AppContext
|
||||
// keep this catch case for compatibility
|
||||
doDispatch = false;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
processException(e);
|
||||
|
||||
@ -2264,15 +2264,14 @@ public abstract class KeyboardFocusManager
|
||||
temporary, descendant, cause);
|
||||
// Fix 5028014. Rolled out.
|
||||
// SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
|
||||
SunToolkit.postEvent(currentFocusOwner.appContext,
|
||||
currentFocusOwnerEvent);
|
||||
SunToolkit.postEvent(currentFocusOwnerEvent);
|
||||
}
|
||||
FocusEvent newFocusOwnerEvent =
|
||||
new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
|
||||
temporary, currentFocusOwner, cause);
|
||||
// Fix 5028014. Rolled out.
|
||||
// SunToolkit.postPriorityEvent(newFocusOwnerEvent);
|
||||
SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
|
||||
SunToolkit.postEvent(newFocusOwnerEvent);
|
||||
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
|
||||
focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, 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
|
||||
@ -27,7 +27,6 @@ package java.awt;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
/**
|
||||
@ -51,22 +50,16 @@ class SentEvent extends AWTEvent implements ActiveEvent {
|
||||
|
||||
boolean dispatched;
|
||||
private AWTEvent nested;
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
private AppContext toNotify;
|
||||
|
||||
SentEvent() {
|
||||
this(null);
|
||||
}
|
||||
SentEvent(AWTEvent nested) {
|
||||
this(nested, null);
|
||||
}
|
||||
SentEvent(AWTEvent nested, AppContext toNotify) {
|
||||
super((nested != null)
|
||||
? nested.getSource()
|
||||
: Toolkit.getDefaultToolkit(),
|
||||
ID);
|
||||
this.nested = nested;
|
||||
this.toNotify = toNotify;
|
||||
}
|
||||
|
||||
public void dispatch() {
|
||||
@ -76,9 +69,6 @@ class SentEvent extends AWTEvent implements ActiveEvent {
|
||||
}
|
||||
} finally {
|
||||
dispatched = true;
|
||||
if (toNotify != null) {
|
||||
SunToolkit.postEvent(toNotify, new SentEvent());
|
||||
}
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
@ -86,9 +76,6 @@ class SentEvent extends AWTEvent implements ActiveEvent {
|
||||
}
|
||||
final void dispose() {
|
||||
dispatched = true;
|
||||
if (toNotify != null) {
|
||||
SunToolkit.postEvent(toNotify, new SentEvent());
|
||||
}
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2026, 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
|
||||
@ -211,8 +211,6 @@ class WaitDispatchSupport implements SecondaryLoop {
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
// Dispose SequencedEvent we are dispatching on the current
|
||||
// AppContext, to prevent us from hang - see 4531693 for details
|
||||
SequencedEvent currentSE = KeyboardFocusManager.
|
||||
getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
|
||||
if (currentSE != null) {
|
||||
|
||||
@ -164,11 +164,8 @@ public abstract class EmbeddedFrame extends Frame
|
||||
}
|
||||
|
||||
/**
|
||||
* Because there may be many AppContexts, and we can't be sure where this
|
||||
* EmbeddedFrame is first created or shown, we can't automatically determine
|
||||
* the correct KeyboardFocusManager to attach to as KeyEventDispatcher.
|
||||
* Those who want to use the functionality of traversing out of the EmbeddedFrame
|
||||
* must call this method on the AppContext. After that, all the changes
|
||||
* must call this method. After that, all the changes
|
||||
* can be handled automatically, including possible replacement of
|
||||
* KeyboardFocusManager.
|
||||
*/
|
||||
@ -184,7 +181,7 @@ public abstract class EmbeddedFrame extends Frame
|
||||
|
||||
/**
|
||||
* Needed to avoid memory leak: we register this EmbeddedFrame as a listener with
|
||||
* KeyboardFocusManager of an AppContext. We don't want the KFM to keep
|
||||
* the KeyboardFocusManager. We don't want the KFM to keep
|
||||
* reference to our EmbeddedFrame forever if the Frame is no longer in use, so we
|
||||
* add listeners in show() and remove them in hide().
|
||||
*/
|
||||
@ -198,7 +195,7 @@ public abstract class EmbeddedFrame extends Frame
|
||||
|
||||
/**
|
||||
* Needed to avoid memory leak: we register this EmbeddedFrame as a listener with
|
||||
* KeyboardFocusManager of an AppContext. We don't want the KFM to keep
|
||||
* the KeyboardFocusManager. We don't want the KFM to keep
|
||||
* reference to our EmbeddedFrame forever if the Frame is no longer in use, so we
|
||||
* add listeners in show() and remove them in hide().
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2026, 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
|
||||
@ -61,7 +61,7 @@ public abstract class GlobalCursorManager {
|
||||
}
|
||||
}
|
||||
if (shouldPost) {
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(heavy), in);
|
||||
SunToolkit.postEvent(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2026, 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
|
||||
@ -127,7 +127,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
focusLog.finer("Posting focus event: " + fl);
|
||||
}
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
|
||||
SunToolkit.postEvent(fl);
|
||||
}
|
||||
|
||||
FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
|
||||
@ -136,7 +136,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
focusLog.finer("Posting focus event: " + fg);
|
||||
}
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
|
||||
SunToolkit.postEvent(fg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2026, 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
|
||||
@ -93,7 +93,7 @@ public class PaintEventDispatcher {
|
||||
* This method is invoked from the toolkit thread when the surface
|
||||
* data of the component needs to be replaced. The method run() of
|
||||
* the Runnable argument performs surface data replacing, run()
|
||||
* should be invoked on the EDT of this component's AppContext.
|
||||
* should be invoked on the EDT.
|
||||
* Returns true if the Runnable has been enqueued to be invoked
|
||||
* on the EDT.
|
||||
* (Fix 6255371.)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2026, 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
|
||||
@ -2480,30 +2480,12 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
* SunGraphicsEnvironment it performs the same initialization as is
|
||||
* performed normally. There may be some duplication of effort, but
|
||||
* that code is already written to be able to perform properly if called
|
||||
* to duplicate work. The main difference is that if we detect we are
|
||||
* in an AppContext environment these new fonts
|
||||
* are not placed in the "default" maps but into an AppContext instance.
|
||||
* The font lookup mechanism in java.awt.Font.getFont2D() is also updated
|
||||
* so that look-up for composite fonts will in that case always
|
||||
* do a lookup rather than returning a cached result.
|
||||
* This is inefficient but necessary else singleton java.awt.Font
|
||||
* instances would not retrieve the correct Font2D for the appcontext.
|
||||
* sun.font.FontManager.findFont2D is also updated to that it uses
|
||||
* a name map cache specific to that appcontext.
|
||||
*
|
||||
* Getting an AppContext is expensive, so there is a global variable
|
||||
* that records whether these methods have ever been called and can
|
||||
* avoid the expense for almost all applications. Once the correct
|
||||
* CompositeFont is associated with the Font, everything should work
|
||||
* through existing mechanisms.
|
||||
* A special case is that GraphicsEnvironment.getAllFonts() must
|
||||
* return an AppContext specific list.
|
||||
* to duplicate work.
|
||||
*
|
||||
* Calling the methods below is "heavyweight" but it is expected that
|
||||
* these methods will be called very rarely.
|
||||
*
|
||||
* If _usingAlternateComposites is true, we are not in an "AppContext"
|
||||
* environment and the (single) application has selected
|
||||
* If _usingAlternateComposites is true, the application has selected
|
||||
* an alternate composite font behaviour.
|
||||
*
|
||||
* - Printing: The implementation delegates logical fonts to an AWT
|
||||
|
||||
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6799345
|
||||
* @key headful
|
||||
* @summary Tests that no exceptions are thrown from TimerQueue and
|
||||
* SwingWorker on AppContext shutdown
|
||||
* @author art
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main TestShutdown
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import sun.awt.*;
|
||||
|
||||
public class TestShutdown
|
||||
{
|
||||
private static AppContext targetAppContext;
|
||||
|
||||
private static JFrame f;
|
||||
private static JTextField tf;
|
||||
|
||||
private static volatile boolean exceptionsOccurred = false;
|
||||
private static volatile boolean appcontextInitDone = false;
|
||||
|
||||
private static int timerValue = 0;
|
||||
|
||||
public static void main(String[] args)
|
||||
throws Exception
|
||||
{
|
||||
ThreadGroup tg = new TestThreadGroup("TTG");
|
||||
Thread t = new Thread(tg, new TestRunnable(), "InitThread");
|
||||
t.start();
|
||||
|
||||
while (!appcontextInitDone)
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
targetAppContext.dispose();
|
||||
|
||||
if (exceptionsOccurred)
|
||||
{
|
||||
throw new RuntimeException("Test FAILED: some exceptions occurred");
|
||||
}
|
||||
}
|
||||
|
||||
static void initGUI()
|
||||
{
|
||||
f = new JFrame("F");
|
||||
f.setBounds(100, 100, 200, 100);
|
||||
tf = new JTextField("Test");
|
||||
f.add(tf);
|
||||
f.setVisible(true);
|
||||
}
|
||||
|
||||
static void startGUI()
|
||||
{
|
||||
// caret blink Timer
|
||||
tf.requestFocusInWindow();
|
||||
|
||||
// misc Timer
|
||||
ActionListener al = new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent ae)
|
||||
{
|
||||
System.out.println("Timer tick: " + timerValue++);
|
||||
}
|
||||
};
|
||||
new javax.swing.Timer(30, al).start();
|
||||
}
|
||||
|
||||
static class TestThreadGroup extends ThreadGroup
|
||||
{
|
||||
public TestThreadGroup(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void uncaughtException(Thread thread, Throwable t)
|
||||
{
|
||||
if (t instanceof ThreadDeath)
|
||||
{
|
||||
// this one is expected, rethrow
|
||||
throw (ThreadDeath)t;
|
||||
}
|
||||
System.err.println("Test FAILED: an exception is caught in the " +
|
||||
"target thread group on thread " + thread.getName());
|
||||
t.printStackTrace(System.err);
|
||||
exceptionsOccurred = true;
|
||||
}
|
||||
}
|
||||
|
||||
static class TestRunnable implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
SunToolkit stk = (SunToolkit)Toolkit.getDefaultToolkit();
|
||||
targetAppContext = stk.createNewAppContext();
|
||||
|
||||
// create and show frame and text field
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
initGUI();
|
||||
}
|
||||
});
|
||||
stk.realSync();
|
||||
|
||||
// start some Timers
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
startGUI();
|
||||
}
|
||||
});
|
||||
|
||||
// start multiple SwingWorkers
|
||||
while (!Thread.interrupted())
|
||||
{
|
||||
try
|
||||
{
|
||||
new TestSwingWorker().execute();
|
||||
Thread.sleep(40);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// exception here is expected, skip
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TestSwingWorker extends SwingWorker<String, Integer>
|
||||
{
|
||||
@Override
|
||||
public String doInBackground()
|
||||
{
|
||||
Random r = new Random();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
int delay = r.nextInt() % 50;
|
||||
Thread.sleep(delay);
|
||||
publish(delay);
|
||||
}
|
||||
catch (Exception z)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!appcontextInitDone)
|
||||
{
|
||||
appcontextInitDone = true;
|
||||
}
|
||||
return "Done";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(java.util.List<Integer> chunks)
|
||||
{
|
||||
for (Integer i : chunks)
|
||||
{
|
||||
System.err.println("Processed: " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, 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 8012933
|
||||
* @summary Tests (although somewhat indirectly) that createNewAppContext()
|
||||
* immediately followed by dispose() works correctly
|
||||
* @author Leonid Romanov
|
||||
* @modules java.desktop/sun.awt
|
||||
*/
|
||||
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.AppContext;
|
||||
|
||||
public class Test8012933 {
|
||||
private AppContext appContext = null;
|
||||
final ThreadGroup threadGroup = new ThreadGroup("test thread group");
|
||||
final Object lock = new Object();
|
||||
boolean isCreated = false;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SunToolkit.createNewAppContext();
|
||||
new Test8012933().test();
|
||||
}
|
||||
|
||||
private void test() throws Exception {
|
||||
createAppContext();
|
||||
long startTime = System.currentTimeMillis();
|
||||
appContext.dispose();
|
||||
long endTime = System.currentTimeMillis();
|
||||
|
||||
// In case of the bug, calling dispose() when there is no EQ
|
||||
// dispatch thread running fails to create it, so it takes
|
||||
// almost 10 sec to return from dispose(), which is spent
|
||||
// waiting on the notificationLock.
|
||||
if ((endTime - startTime) > 9000) {
|
||||
throw new RuntimeException("Returning from dispose() took too much time, probably a bug");
|
||||
}
|
||||
}
|
||||
|
||||
private void createAppContext() {
|
||||
isCreated = false;
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
appContext = SunToolkit.createNewAppContext();
|
||||
synchronized (lock) {
|
||||
isCreated = true;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final Thread thread = new Thread(threadGroup, runnable, "creates app context");
|
||||
synchronized (lock) {
|
||||
thread.start();
|
||||
while (!isCreated) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appContext == null) {
|
||||
throw new RuntimeException("failed to create app context.");
|
||||
} else {
|
||||
System.out.println("app context was created.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user