Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java
38827 views
/*1* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.lwawt;2627import java.awt.*;28import java.awt.List;29import java.awt.datatransfer.*;30import java.awt.image.*;31import java.awt.peer.*;32import java.security.*;33import java.util.*;3435import sun.awt.*;36import sun.print.*;37import sun.security.util.SecurityConstants;38import sun.misc.ThreadGroupUtils;3940import static sun.lwawt.LWWindowPeer.PeerType;4142public abstract class LWToolkit extends SunToolkit implements Runnable {4344private final static int STATE_NONE = 0;45private final static int STATE_INIT = 1;46private final static int STATE_MESSAGELOOP = 2;47private final static int STATE_SHUTDOWN = 3;48private final static int STATE_CLEANUP = 4;49private final static int STATE_DONE = 5;5051private int runState = STATE_NONE;5253private Clipboard clipboard;54private MouseInfoPeer mouseInfoPeer;5556/**57* Dynamic Layout Resize client code setting.58*/59private volatile boolean dynamicLayoutSetting = true;6061protected LWToolkit() {62}6364/*65* This method is called by subclasses to start this toolkit66* by launching the message loop.67*68* This method waits for the toolkit to be completely initialized69* and returns before the message pump is started.70*/71protected final void init() {72AWTAutoShutdown.notifyToolkitThreadBusy();7374ThreadGroup rootTG = AccessController.doPrivileged(75(PrivilegedAction<ThreadGroup>) ThreadGroupUtils::getRootThreadGroup);7677Runtime.getRuntime().addShutdownHook(78new Thread(rootTG, () -> {79shutdown();80waitForRunState(STATE_CLEANUP);81})82);8384Thread toolkitThread = new Thread(rootTG, this, "AWT-LW");85toolkitThread.setDaemon(true);86toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);87toolkitThread.start();8889waitForRunState(STATE_MESSAGELOOP);90}9192/*93* Implemented in subclasses to initialize platform-dependent94* part of the toolkit (open X display connection, create95* toolkit HWND, etc.)96*97* This method is called on the toolkit thread.98*/99protected abstract void platformInit();100101/*102* Sends a request to stop the message pump.103*/104public final void shutdown() {105setRunState(STATE_SHUTDOWN);106platformShutdown();107}108109/*110* Implemented in subclasses to release all the platform-111* dependent resources. Called after the message loop is112* terminated.113*114* Could be called (always called?) on a non-toolkit thread.115*/116protected abstract void platformShutdown();117118/*119* Implemented in subclasses to release all the platform120* resources before the application is terminated.121*122* This method is called on the toolkit thread.123*/124protected abstract void platformCleanup();125126private synchronized int getRunState() {127return runState;128}129130private synchronized void setRunState(int state) {131runState = state;132notifyAll();133}134135public final boolean isTerminating() {136return getRunState() >= STATE_SHUTDOWN;137}138139private void waitForRunState(int state) {140while (getRunState() < state) {141try {142synchronized (this) {143wait();144}145} catch (InterruptedException z) {146// TODO: log147break;148}149}150}151152@Override153public final void run() {154setRunState(STATE_INIT);155platformInit();156AWTAutoShutdown.notifyToolkitThreadFree();157setRunState(STATE_MESSAGELOOP);158while (getRunState() < STATE_SHUTDOWN) {159try {160platformRunMessage();161if (Thread.currentThread().isInterrupted()) {162if (AppContext.getAppContext().isDisposed()) {163break;164}165}166} catch (ThreadDeath td) {167//XXX: if there isn't native code on the stack, the VM just168//kills the thread right away. Do we expect to catch it169//nevertheless?170break;171} catch (Throwable t) {172// TODO: log173System.err.println("Exception on the toolkit thread");174t.printStackTrace(System.err);175}176}177//XXX: if that's a secondary loop, jump back to the STATE_MESSAGELOOP178setRunState(STATE_CLEANUP);179AWTAutoShutdown.notifyToolkitThreadFree();180platformCleanup();181setRunState(STATE_DONE);182}183184/*185* Process the next message(s) from the native event queue.186*187* Initially, all the LWToolkit implementations were supposed188* to have the similar message loop sequence: check if any events189* available, peek events, wait. However, the later analysis shown190* that X11 and Windows implementations are really different, so191* let the subclasses do whatever they require.192*/193protected abstract void platformRunMessage();194195public static LWToolkit getLWToolkit() {196return (LWToolkit)Toolkit.getDefaultToolkit();197}198199// ---- TOPLEVEL PEERS ---- //200201/*202* Note that LWWindowPeer implements WindowPeer, FramePeer203* and DialogPeer interfaces.204*/205protected LWWindowPeer createDelegatedPeer(Window target,206PlatformComponent platformComponent,207PlatformWindow platformWindow,208PeerType peerType) {209LWWindowPeer peer = new LWWindowPeer(target, platformComponent, platformWindow, peerType);210targetCreatedPeer(target, peer);211peer.initialize();212return peer;213}214215@Override216public final FramePeer createLightweightFrame(LightweightFrame target) {217PlatformComponent platformComponent = createLwPlatformComponent();218PlatformWindow platformWindow = createPlatformWindow(PeerType.LW_FRAME);219LWLightweightFramePeer peer = new LWLightweightFramePeer(target,220platformComponent,221platformWindow);222targetCreatedPeer(target, peer);223peer.initialize();224return peer;225}226227@Override228public final WindowPeer createWindow(Window target) {229PlatformComponent platformComponent = createPlatformComponent();230PlatformWindow platformWindow = createPlatformWindow(PeerType.SIMPLEWINDOW);231return createDelegatedPeer(target, platformComponent, platformWindow, PeerType.SIMPLEWINDOW);232}233234@Override235public final FramePeer createFrame(Frame target) {236PlatformComponent platformComponent = createPlatformComponent();237PlatformWindow platformWindow = createPlatformWindow(PeerType.FRAME);238return createDelegatedPeer(target, platformComponent, platformWindow, PeerType.FRAME);239}240241@Override242public DialogPeer createDialog(Dialog target) {243PlatformComponent platformComponent = createPlatformComponent();244PlatformWindow platformWindow = createPlatformWindow(PeerType.DIALOG);245return createDelegatedPeer(target, platformComponent, platformWindow, PeerType.DIALOG);246}247248@Override249public final FileDialogPeer createFileDialog(FileDialog target) {250FileDialogPeer peer = createFileDialogPeer(target);251targetCreatedPeer(target, peer);252return peer;253}254255// ---- LIGHTWEIGHT COMPONENT PEERS ---- //256257@Override258public final ButtonPeer createButton(Button target) {259PlatformComponent platformComponent = createPlatformComponent();260LWButtonPeer peer = new LWButtonPeer(target, platformComponent);261targetCreatedPeer(target, peer);262peer.initialize();263return peer;264}265266@Override267public final CheckboxPeer createCheckbox(Checkbox target) {268PlatformComponent platformComponent = createPlatformComponent();269LWCheckboxPeer peer = new LWCheckboxPeer(target, platformComponent);270targetCreatedPeer(target, peer);271peer.initialize();272return peer;273}274275@Override276public final ChoicePeer createChoice(Choice target) {277PlatformComponent platformComponent = createPlatformComponent();278LWChoicePeer peer = new LWChoicePeer(target, platformComponent);279targetCreatedPeer(target, peer);280peer.initialize();281return peer;282}283284@Override285public final LabelPeer createLabel(Label target) {286PlatformComponent platformComponent = createPlatformComponent();287LWLabelPeer peer = new LWLabelPeer(target, platformComponent);288targetCreatedPeer(target, peer);289peer.initialize();290return peer;291}292293@Override294public final CanvasPeer createCanvas(Canvas target) {295PlatformComponent platformComponent = createPlatformComponent();296LWCanvasPeer<?, ?> peer = new LWCanvasPeer<>(target, platformComponent);297targetCreatedPeer(target, peer);298peer.initialize();299return peer;300}301302@Override303public final ListPeer createList(List target) {304PlatformComponent platformComponent = createPlatformComponent();305LWListPeer peer = new LWListPeer(target, platformComponent);306targetCreatedPeer(target, peer);307peer.initialize();308return peer;309}310311@Override312public final PanelPeer createPanel(Panel target) {313PlatformComponent platformComponent = createPlatformComponent();314LWPanelPeer peer = new LWPanelPeer(target, platformComponent);315targetCreatedPeer(target, peer);316peer.initialize();317return peer;318}319320@Override321public final ScrollPanePeer createScrollPane(ScrollPane target) {322PlatformComponent platformComponent = createPlatformComponent();323LWScrollPanePeer peer = new LWScrollPanePeer(target, platformComponent);324targetCreatedPeer(target, peer);325peer.initialize();326return peer;327}328329@Override330public final ScrollbarPeer createScrollbar(Scrollbar target) {331PlatformComponent platformComponent = createPlatformComponent();332LWScrollBarPeer peer = new LWScrollBarPeer(target, platformComponent);333targetCreatedPeer(target, peer);334peer.initialize();335return peer;336}337338@Override339public final TextAreaPeer createTextArea(TextArea target) {340PlatformComponent platformComponent = createPlatformComponent();341LWTextAreaPeer peer = new LWTextAreaPeer(target, platformComponent);342targetCreatedPeer(target, peer);343peer.initialize();344return peer;345}346347@Override348public final TextFieldPeer createTextField(TextField target) {349PlatformComponent platformComponent = createPlatformComponent();350LWTextFieldPeer peer = new LWTextFieldPeer(target, platformComponent);351targetCreatedPeer(target, peer);352peer.initialize();353return peer;354}355356// ---- NON-COMPONENT PEERS ---- //357358@Override359public final ColorModel getColorModel() throws HeadlessException {360return GraphicsEnvironment.getLocalGraphicsEnvironment()361.getDefaultScreenDevice()362.getDefaultConfiguration().getColorModel();363}364365@Override366public final boolean isDesktopSupported() {367return true;368}369370@Override371public final KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {372return LWKeyboardFocusManagerPeer.getInstance();373}374375@Override376public final synchronized MouseInfoPeer getMouseInfoPeer() {377if (mouseInfoPeer == null) {378mouseInfoPeer = createMouseInfoPeerImpl();379}380return mouseInfoPeer;381}382383protected final MouseInfoPeer createMouseInfoPeerImpl() {384return new LWMouseInfoPeer();385}386387protected abstract PlatformWindow getPlatformWindowUnderMouse();388389@Override390public final PrintJob getPrintJob(Frame frame, String doctitle,391Properties props) {392return getPrintJob(frame, doctitle, null, null);393}394395@Override396public final PrintJob getPrintJob(Frame frame, String doctitle,397JobAttributes jobAttributes,398PageAttributes pageAttributes) {399if (GraphicsEnvironment.isHeadless()) {400throw new IllegalArgumentException();401}402403PrintJob2D printJob = new PrintJob2D(frame, doctitle, jobAttributes, pageAttributes);404405if (!printJob.printDialog()) {406printJob = null;407}408409return printJob;410}411412@Override413public final Clipboard getSystemClipboard() {414SecurityManager security = System.getSecurityManager();415if (security != null) {416security.checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION);417}418419synchronized (this) {420if (clipboard == null) {421clipboard = createPlatformClipboard();422}423}424return clipboard;425}426427protected abstract SecurityWarningWindow createSecurityWarning(428Window ownerWindow, LWWindowPeer ownerPeer);429430// ---- DELEGATES ---- //431432public abstract Clipboard createPlatformClipboard();433434/*435* Creates a delegate for the given peer type (window, frame, dialog, etc.)436*/437protected abstract PlatformWindow createPlatformWindow(PeerType peerType);438439protected abstract PlatformComponent createPlatformComponent();440441protected abstract PlatformComponent createLwPlatformComponent();442443protected abstract FileDialogPeer createFileDialogPeer(FileDialog target);444445// ---- UTILITY METHODS ---- //446447/*448* Expose non-public targetToPeer() method.449*/450public final static Object targetToPeer(Object target) {451return SunToolkit.targetToPeer(target);452}453454/*455* Expose non-public targetDisposedPeer() method.456*/457public final static void targetDisposedPeer(Object target, Object peer) {458SunToolkit.targetDisposedPeer(target, peer);459}460461/*462* Returns the current cursor manager.463*/464public abstract LWCursorManager getCursorManager();465466public static void postEvent(AWTEvent event) {467postEvent(targetToAppContext(event.getSource()), event);468}469470@Override471public final void grab(final Window w) {472final Object peer = AWTAccessor.getComponentAccessor().getPeer(w);473if (peer != null) {474((LWWindowPeer) peer).grab();475}476}477478@Override479public final void ungrab(final Window w) {480final Object peer = AWTAccessor.getComponentAccessor().getPeer(w);481if (peer != null) {482((LWWindowPeer) peer).ungrab(false);483}484}485486@Override487protected final Object lazilyLoadDesktopProperty(final String name) {488if (name.equals("awt.dynamicLayoutSupported")) {489return isDynamicLayoutSupported();490}491return super.lazilyLoadDesktopProperty(name);492}493494@Override495public final void setDynamicLayout(final boolean dynamic) {496dynamicLayoutSetting = dynamic;497}498499@Override500protected final boolean isDynamicLayoutSet() {501return dynamicLayoutSetting;502}503504@Override505public final boolean isDynamicLayoutActive() {506// "Live resizing" is active by default and user's data is ignored.507return isDynamicLayoutSupported();508}509510/**511* Returns true if dynamic layout of Containers on resize is supported by512* the underlying operating system and/or window manager.513*/514protected final boolean isDynamicLayoutSupported() {515// "Live resizing" is supported by default.516return true;517}518}519520521